简体   繁体   中英

Return values to presenting view controller when navigation back button pressed

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:

  1. 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.

  2. 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.

  3. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM