I currently have a UIView / UIScrollView that is displayed within a modal view. It is basically a detail view that provides a view of a page when the user clicks a link. When the view is dismissed and then brought up again (when the user clicks another button), the previously-loaded content is still visible and the new content loads "on top" of the last content. This makes sense because the instance of the UIView / UIScrollView persists and is only released when the memory is needed.
However, I would like to completely clear the UIView / UIScrollView when the modal view is dismissed so that 1) content is cleared and 2) memory is freed.
rightDetailedView = [[UIScrollView alloc] init];
rightDetailedView.backgroundColor = [UIColor whiteColor];
The above code initializes the view every time this method is called and to my knowledge when we are recreating a view the background will be transparent so we need to add backgroundColor with whiteColr or some color.
Thanks,
Kris :)
Related
In my app, I have an UITableView with asynchronous data loading : when the view controller is loaded I show a modal activity spinner and start the HTTP request. When it is completed I hide the spinner and execute reloadData() on my table view. I also return response?.count ?? 0 as a number of rows to make sure that the list it initially empty when the data is not ready yet.
It works like a charm, but I have an issue with VoiceOver : when opening the view controller, VoiceOver goes into the table and says "empty list". When the data is loaded it goes to the last element of the table.
This behavior is not very optimal : I would like VoiceOver to not focus the table while it's empty (it doesn't need to focus the modal spinner since we already have a sound while loading) and then go to the first element when it's loaded.
How may I do that ?
You want to set up your loading overlay screen as a modal view. Modal means that the things behind the view are not actionable (or focusable by VoiceOver).
//Instantiate a view controller with your loading spinner.
_modalDialogViewController = [[UIStoryboard storyboardWithName:#"ModalDialog" bundle:[NSBundle mainBundle]]
instantiateViewControllerWithIdentifier:#"AccessibleSpinnerModal"];
//Make this view controller modal, meaning only things on this screen will be actionable/focusable.
_modalDialogViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
You may also then need to use accessibility notifications in either of these styles.
//Announce that content is loading directly
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, "Stuff is laoding");
Or
//Shift focus to the view in your modal that is sharing the status of the loading content.
UIAccessibilityPostNotification(UIAccessibilityLayoutChanged, spinnerView);
This will cause focus to move to that view.
I have a Nib in my storyboard which is not connected to anything but I'm instantiating it as a subview thusly:
-(void)LoadCameraOverlayView
{
CameraOverlayViewController *cameraVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CameraOverlayNib"];
cameraVC.view.userInteractionEnabled = YES;
[self.view addSubview:cameraVC.view];
}
The UIViewController has a camera with feedback which is working fine and a button which (when I segue to the view controller also works fine.)
The button is linked to a Touch Down event and Touch Up Inside event.
When I click the button I can see it is changing visually from its default state to its focused or highlighted state however none of the code seems to be executing. If I put an NSLog in the ViewDidLoad I can see that in the console but not for the linked method. However if I segue to the view it does work.
What's going on?
I looked at other solutions but I don't think it could be that there is a view in the way or that the CGRect isn't calibrated correctly or anything since I can see the visual change when clicking the button.
This code violates Rule One of how to use view controllers:
CameraOverlayViewController *cameraVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CameraOverlayNib"];
[self.view addSubview:cameraVC.view];
You cannot simply instantiate a view controller and then add its view manually to the view hierarchy like that. There are very strict rules about this; there is an elaborate "dance" that you must do in order to add a view controller's view to your interface manually, and you are not doing the dance.
The result is that your cameraVC comes into existence, is given no place in the view controller hierarchy, and vanishes in a puff of smoke. There is thus no object for your button to talk to, and so when the button is tapped, nothing happens.
My suggestion would be: use a .xib file, not a storyboard scene, for this view; and after you have loaded it and put it into the interface, use code to configure the button so that it talks to self, your current view controller.
I'm trying to implement the following behavior:
Long press on a collection view brings a full-window view (call it LetterView) to the front
Subsequent gestures/touches are only processed by the LetterView.
(edit: I should mention that I want a transparency effect of seeing the collectionview items beneath LetterView)
I seem to be running into behavior that everyone else is trying to implement, though - my touches get processed by both the LetterView and the collection view. I.e. I can scroll the collection view AND have hits processed by my topmost view. Showing the view hierarchy in XCode clearly shows LetterView at the front, and both the UICollectionView and the LetterView are subviews of UICollectionWrapperView.
LetterView is a UIView subclass with a UIViewController subclass. It's added to the view hierarchy programmatically, inside my UICollectionViewController subclasses's viewDidLoad method, like so:
super.viewDidLoad()
letterDrawingViewController = LetterDrawingViewController()
let viewFrame : CGRect = self.collectionView!.frame
letterDrawingViewController.view = LetterDrawingView.init(frame:viewFrame)
letterDrawingView = letterDrawingViewController.view
self.addChildViewController(letterDrawingViewController)
letterDrawingViewController.didMoveToParentViewController(self)
collectionView?.addSubview(letterDrawingView)
It doesn't appear to be a first responder issue, as I tried overriding canBecomeFirstResponder in LetterView and assigning it first responder status when I move it to the front
I tried setting userInteractionEnabled=FALSE on the CollectionView, but keeping it true on the LetterView after I moved LetterView to the front. This disabled all touch events for both views
I tried setting exclusiveTouch=True for LetterView when I moved it to the front. This didn't appear to do anything.
Aside from any specific tips, are there any general techniques for debugging hit-testing like this? According to the docs on hit-testing in iOS, iOS should prefer the "deepest" subview that returns yes for hitTest:withEvent:, which, since LetterView is a subview of collectionview, and in front of all it's cells, should be the front? Is there any logging I can enable to see a hit test over the view hierarchy in action?
Thank you!
Nate.
If letterView is full screen, you probably don't want to add it as a subview of the collection view like you are. Maybe try adding it to the application's window instead and see how that does. At least in that instance it should intercept all the touch events.
Another method, although admittedly a more fragile feeling one, would be to enable and disable user interaction on the collectionView as you present and dismiss letterView.
So, when letterView is about to be presented, you can call
self.collectionView.userInteractionEnabled = NO;
and if you also know when that view is about to be dismissed you can call
self.collectionView.userInteractionEnabled = YES;
The only thing here to worry about is that you don't get into a bad state where your letterView is not presenting and your collectionView is also ignoring a user's touch. That will feel totally broken.
Whilst I think you can deal with your issue somewhat easily I think you are making a design mistake. It feels like you are trying to code this thinking like a web developper by adding a child view to your view and trying to intercept the touches there like one would do in a modern JavaScript single page app. In iOS I think this is bad design. You should segue or present the new viewController using the methods provided by apple.
So your code should look soothing like:
letterDrawingViewController = LetterDrawingViewController()
self.presentViewController(letterDrawingViewController, animated: true, completion: nil)
iOS8 has the added benefit of allowing you to have awesome custom transitions. Take a look at this : http://www.appcoda.com/custom-segue-animations/
I need to modify a view's modal presentation with this parameters:
1 - Modal view only fills the ipad's right half of the screen.
2 - The animation runs from the left half of the screen.
I have search in iosframeworks.com, cocoacontrols.com, the books from big nerd rach, ios recipes, ios pushing the limits, stackoverflow and google. Is some posibility to do that?
Thanks for your assistance
For testing, after two days of searching answers, I create the following code, I'm executing the following code since the root view controller CMMainView, the viewcontroller CMVistaModal is empty, its doesn't have any overrided method nor xib nor another variable, the device family is iPad
-(IBAction)accion:(id)sender
{
CMVistaModal *modal = [[CMVistaModal alloc] init];
[modal setModalPresentationStyle:UIModalPresentationFormSheet];
[self presentViewController:modal animated:NO completion:nil];
[modal.view.superview setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[modal.view.superview setFrame:CGRectMake(800, 120, 200, 500)];
[UIView animateWithDuration:1 animations:^{
modal.view.superview.transform = CGAffineTransformMakeTranslation(-200, 0);
}];
}
how can i perform the same operation but overriding the methods from CMVistaModal?
Absolutely. Just make a new view and add it to your existing view and animate it into position. You can have another view appear behind it blocking any touches to other views.
Anything is possible. It just depends on how much work you wish to put in.
So a standard UIModalPresentationFormSheet or UIModalPresentationPageSheet comes for free. But what you want isn't standard so you have to bake your own.
What I would do here is create a "fake" modal.
With
XYViewController -> Container View
Container View -> Semi Opaque blocker
-> Half Screen Content
The blocker covers the entire screen and goes in immediately and prevents interaction with the rest of the UI
Then animate the "Half Screen Content" in from the left with a standard frame animate. How you choose to dismiss this fake modal is up to you but if it comes in from left perhaps it should depart to the left.
I have an iPad app that has an MKMapView embedded in a UINavigationController which is displayed in a UITabBar. I am displaying a popover controller over the map with
UIPopoverController *myPopoverController =
[[[UIPopoverController alloc] initWithContentViewController:myContentView]
autorelease];
[myPopoverController presentPopoverFromRect:myRect
inView:mapView
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
The popover displays fine. However, it does not have the nice animated effect: it just immediately appears onscreen. Similarly, when I dismiss it it just disappears without any animation.
Anybody have any idea how I can get the animation to work? Should I try displaying it from another view? Is there some property on something that I might have neglected to set?
Despite the animated:(BOOL) parameter, it appears popovers never animate when presented. I've tried a dozen first and third party apps.
The dismissal should animate however, provided you pass YES to dismissPopoverAnimated:(BOOL)
Assuming your popover animates outside the map view, I would try placing the map view into a container view whose frame is the same size as the map view's. From there, it's trivial to present the popover in the container view.
According to Apple's documentation, MKMapView isn't supposed to be subclassed, so like UIWebView, it strikes me as one of those views whose guts are better left untouched.