When a popover is open it closes if you click of it. Is is possible to stop this? Basically i have the following problem.
When a popover closes i need a function to be processed. If i set a button with a dismiss function from the popover then i can put the function in the dismiss method however this isn't detected if the user clicks of the screen.
So is is possible to stop a popover closing if you click off it.
or
Is it possible to detect this allowing the function i require to be called.
Thanks
James
Can use these two methods, but the second one suits your scenario:
/* Called on the delegate when the popover controller will dismiss the popover.
Return NO to prevent the dismissal of the view.
*/
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController;
/* Called on the delegate when the user has taken action to dismiss the popover.
This is not called when -dismissPopoverAnimated: is called directly.
*/
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController;
Remember to implement the UIPopoverdelegate and set the Delegate to self.
Assuming you are talking about the default behavior of popovers being dismissed when you tap outside of the popover, the solution to prevent this is to make the popover modal.
To do this, set the modalInPopover property to YES on the popover's content view controller.
BTW - if you want to detect when a popover is dismissed by the user by tapping outside of it, you need to implement the UIPopoverControllerDelegate method popoverControllerDidDismissPopover:.
Related
I need a way to change text depending of user input, when user tap back button. I followed that solution: Find out if user pressed the back button in uinavigationcontroller?
and did add following code in viewDidLoad:
if ([self isMovingFromParentViewController]) {
NSLog(#"isMoved");
[self.delegate stringChangedTo:self.myTextField.text atIndex:self.indexToPass];
}
However, nothing changed. More to say, method is not called (NSLog dont output a string).
How could i find a way to call delegate when user tap back button?
That code needs to be in viewWillDisappear: or viewDidDisappear:. not viewDidLoad.
viewDidLoad is called when the view controller's view is loaded. You want to call the delegate when the view controller is being dismissed.
There is also a UINavigationControllerDelegate protocol. You can get notified when a given view controller is shown by implementing either of these:
-navigationController:willShowViewController:animated:
-navigationController:didShowViewController:animated:
ADDENDUM:
In my opinion, using the delegate is a cleaner design, because you get notified precisely when a navigation event occurs. View controller life cycle methods such as -viewDidDisappear:, etc. can get called when you present/dismiss a modal view controller, and require that you add logic to discern those.
What function gets triggered when a user hits the back button on a push page? I need to set some properties before going back to the previous page. ViewWillDisapper is not what I'm looking for
You will want to use either viewWillDisappear or viewDidDisappear to monitor a user going back on a pushed page (assuming you mean this is inside a navigation controller).
Just like when you call your instance method of UINavigationController to "pushViewController:(BOOL)animated:" guess what method is called to POP a view controller? try something like
[self.navigationBar.backButton //Not sure if this is what its called addTarget:self selector:#selector(popViewController)]
and fill in the rest of the method with UIEventTouchUpInside so when the user presses the back button on navigation bar it will jump into you're overrided function.
Make your View inherit UINavigationController protocols and then overide popViewController method.
I suggest looking at UINavigationController class reference if that didn't answer your question.
I'm having trouble piecing this all together. I have a view controller that opens up another (pushes it on to the navigation stack). On that presented view controller, the user enters a value in a text view. When the user pushes the back button in the navigation, I want to be able to pass the value that they entered in the text view back to the presenting controller.
I've looked for a way to use unwind segue with the back button but haven't found anything. When I create my back button (programmatically) I use initWithTitle:style:target:action but I'm not sure how in implementing the action method that I'll be able to access the value set in the presented controller. Might have to use a delegate to link the two, but not sure of the exact integration point for this scenario.
I feel like I'm so close here and a little help would get me there. Thanks!
The two most common models to use for this interaction are for the child view controller to have either a delegate or a completion block. Either would be set in the prepareForSegue method. My personal preference is the completion block method just because it keeps code contained, but ymmv.
There are also multiple models for detecting when your child view controller is dismissed and you need to invoke the delegate and/or completion:
Use a custom back button. Not a fan of this as it can be an issue to create a back button that really looks and acts like the Apple original, especially if supporting iOS 6 and iOS 7.
Hook viewDidDisappear and see if you're still in the navigation controller's viewControllers array. This is better as the back button works right, but it still feels kind of hokey.
Use the UINavigationBarDelegate method navigationBar:shouldPopItem: This is attractive, especially if you have other validation that needs to happen like checking for saved/unsaved values. To implement this you'll have to subclass UINavigationController and forward the method to your child view controller.
EDIT: Details on Option 2:
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if(![self.navigationController.viewControllers containsObject:self])
{
// We're not still in the navigation stack so we must've been
// popped. If we were pushed, viewDidDisappear would be called
// but viewControllers containsObject:self would be true
}
}
EDIT: Clarified Option 3: in your navigation controller subclass
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
UIViewController* top = self.topViewController;
if([top respondsToSelector:#selector(navigationBar:shouldPopItem:)])
return [(id)top navigationBar:navigationBar shouldPopItem:item];
return [super navigationBar:navigationBar shouldPopItem:item];
}
Then you can implement navigationBar:shouldPopItem: in the classes that need the functionality.
the back button does not actually comes up with any event associated with itself so that you can pass the values between the previous and to be Popped ViewController.
You would have to implement Delegate pattern to pass values. In this case as you cant catch when backButton is pressed, you need to use custom leftBarButtonItem or use a image with < in itself.
I'm making a UIPopoverController and displaying it. All is well, content is loading... except I need to dismiss the popover when a button is pressed. The UIPopoverController's delegate is set to self but I don't know how to call a method in the parent view controller.
UIPopoverController has method
- (void)dismissPopoverAnimated:(BOOL)animated
so you can dismiss it directly from itself.
Unless you meant that you want to dismiss popover from its contentViewController, then there is at least dozen of answers regarding that here - for instance similar to this one
Converting an application to work on iPad. Need some help in understanding the sequence of processing popovers, dismissals and activity indicators.
Here is the desired sequence:
Present a tableview wrapped in a navigation controller inside a popover.
Select a row from the table.
Send info from that row to the primary view controller (parent).
Dismiss the popover completely.
Show an activity indicator showing that processing is occurring.
Do some processing.
Make the activity indicator disappear.
Draw the graphics on the primary view.
I have been able to do all the above except the popover stays on the screen until all the processing is done and the graphics drawn. The activity indicator shows up momentarily when the popover disappears. I have tried delegates, notifications and setters, to no avail. It appears that all the processes inside a method don't necessarily execute in sequence and the popover view holds on until everything is executed (in this case the select row method).
Where do I put both the processing code and the activity indicators so everything works in the right order?
This is a very straight forward implementation
Check the following list
Create a delegate of the viewController shown in popover
Set the delegate of popover viewController as main viewController
Keep a reference of popover in main viewController to dismiss it once event is received.
Once event is received dismiss the popover after getting the selected value
Show an activity indicator view or HUD
Dismiss the activity indicator once processing is done
Source code for a demo app doing this.
Make the UIPopoverController instance a iVar. Alloc Init it with your required view controller on some button method or whatever you have designed. Make a protocol from your popover controller's root view controller and make the parent view controller conform to it. On the didSelectRowAtIndexPath: method, call that delegate to popover's parent view controller. On the message reception in parent view controller, dismiss the popover controller instance and do your processing there. (Do Manage the memory well if the project does not support ARC because the popover might be alloc inited several times.)