0

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!

Jeremy Hicks
  • 3,690
  • 5
  • 40
  • 52

2 Answers2

2

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.

David Berry
  • 40,941
  • 12
  • 84
  • 95
  • Amazing answer! Still in the middle of implementing this and running into an issue - I've set my child controller to use UINavigationBarDelegate but the navigationBar:shouldPopItem method doesn't get called. Won't that method only get called in the class that is actually extending NavigationController? – Jeremy Hicks Mar 19 '14 at 18:02
  • I ended up using a delegate but I'm really curious how to implement a completion block for the child view controller. I've not been able to find anything that references any such thing. – Jeremy Hicks Mar 19 '14 at 18:03
  • Found this as a great example of completion block: http://stackoverflow.com/questions/13653048/dismissviewcontrolleranimated-completion-block-presenter-view-and-modal-view-flo I'm still not clear on the last step. I'm now trying option 2. from above but not sure what it means to see if you're still in the navigation controller's viewControllers array. Anyhow, it appears to be working now! – Jeremy Hicks Mar 19 '14 at 18:43
1

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.

Community
  • 1
  • 1
Shubhank
  • 21,721
  • 8
  • 65
  • 83