Search code examples
iphoneiosuipickerview

get the selected item from second view


I have two views, each with its own view controller. The first view has two buttons ("Button" and "Button2"). When I click on "Button", I load the second view controller, which contains a UIPickerView, which hovers over of first view (by performing addSubview) as is shown in the image below). When I click on the "Item" button of this second view, I hide the view with the UIPickerView. When I click on the "Item" button, I not only want to hide the view with the UIPickerView, but also to set name of button with item selected from UIPickerView.

(Each of these two view has its own view controller.)

screen snapshot


Solution

  • The process is as follows:

    1. Define a protocol for the child view controller to inform the parent view controller:

      //
      //  ChildViewDelegate.h
      //
      
      #import <Foundation/Foundation.h>
      
      @protocol ChildViewDelegate <NSObject>
      
      - (void)didUpdateValueX:(NSString *)string;
      
      @end
      

      Obviously, replace didUpdateValueX with a more meaningful name.

    2. Define the parent view controller to conform to that protocol:

      //
      //  ViewController.h
      //
      
      #import <UIKit/UIKit.h>
      #import "ChildViewDelegate.h"
      
      @interface ViewController : UIViewController <ChildViewDelegate>
      
      // the rest of your interface here
      
      @end
      
    3. Make sure the parent controller implements the method from that protocol:

      - (void)didUpdateValueX:(NSString *)string
      {
          // do whatever you want with it
      }
      
    4. When the parent adds the child, make sure to call the necessary custom container calls, notably addChildViewController and didMoveToParentViewController:

      UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"child"];
      [self addChildViewController:controller];
      controller.view.frame = ...;
      [self.view addSubview:controller.view];
      [controller didMoveToParentViewController:self];
      
    5. When the child is ready to inform the parent and dismiss itself, it does something like:

      if ([self.parentViewController conformsToProtocol:@protocol(ChildViewDelegate)])
      {
          [(id<ChildViewDelegate>)self.parentViewController didUpdateValueX:someStringValue];
      
          [self willMoveToParentViewController:nil];
          [self.view removeFromSuperview];
          [self removeFromParentViewController];
      }
      else
      {
          NSLog(@"%s: %@ does not conform to ChildViewDelegate!!!", __FUNCTION__, self.parentViewController);
      }
      

      This calls the protocol method and then removes itself (calling the necessary containment methods, willMoveToParentViewController:nil and removeFromParentViewController).

    Theoretically, you could simplify this (keep all the containment stuff, but abandon the protocol) if your parent had a class property, and the child could theoretically reference that directly, but best practice is to use a protocol, so child controllers are a little more agnostic about their parent controllers.

    See Creating Custom Container View Controllers in the View Controller Programming Guide. For a discussion about why it's important to use these container calls in the first place, see the WWDC 2011 video Implementing UIViewController Containment.