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.
Related
If I have multiple view controllers being presented and dismissed in any order, can I be sure that iOS calls viewWillAppear methods in the right order (i.e. order of appearance)?
I cannot find any specific information about this in the documentation.
I think this is all you need to know about viewWillAppear from the docs:
This method is called before the view controller's view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented. If you override this method, you must call super at some point in your implementation.
Only thing that comes to mind that might not be absolutely clear is that this callback is called on the presenting view controller when presented view controller is going to be dismissed (so presenting view controller is going to appear again).
Therefore if A is a root, A.viewWillAppear will be called before it will appear on the screen. Then, if A presents B, just before B becomes visible, B.viewWillAppear will be called. And when B is being dismissed, A.viewWillAppear will get called again, since its view will appear again.
viewWillAppear() is called the first time the view is displayed and it is also called when the view is displayed again, so it can be called multiple times during the life of the view controller object.
It’s called when the view is about to appear as a result of the user tapping the back button, closing dialog, or when the view controller’s tab is selected in a tab bar controller, or a variety of other reasons. Make sure to call super.viewWillAppear() at some point in the implementation
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.
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:.
I'm wondering if there's a callback, similar to prepareForSegue, which gets called when returning to a parent UIViewController, when the user preses the [back] button.
I'd also like to get the information, from which child view controller the user came from, meaning, in which view controller the user pressed the back button.
Use delegate methods if you want to get data back from a pushed (or modal) VC. If you need an example, check here