Display ABPeoplePickerNavigationController using storyboard segue

I have a new project where I want to display a People Picker, when a button is touched.

So I have a UIButton that segues to a generic UIViewController with the identifier showContacts. I set the class of this ViewController to ABPeoplePickerNavigationController.

  • os x Swift: get file path using drag and drop
  • Hidden Features of Xcode
  • Populating NSImage with data from an asynchronous NSURLConnection
  • Swift NSImage to CGImage
  • How to display the current project version of my App to the user?
  • How to override a fullscreen game with keywindow borderless window (overlay)?
  • Now in my root ViewController I have this code to initialize my picker:

    #pragma mark - Segues
    
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    
        if([segue.identifier isEqualToString:@"showContacts"]){
            ABPeoplePickerNavigationController *ppnc = segue.destinationViewController;
            ppnc.peoplePickerDelegate = self;
            ppnc.addressBook = ABAddressBookCreate(); 
            ppnc.displayedProperties = [NSArray arrayWithObject:[NSNumber numberWithInt:kABPersonPhoneProperty]];
        }
    }
    

    Although I have added test contacts to my Simulator Address book the results looks like this:

    no picker http://i.minus.com/jbwUQyLr36ChHo.png

    With the following code, which is very similar to what I do in the prepareForSegue: method, I manage to show a picker via an IBAction:

    - (IBAction)showPicker:(id)sender {
    
        ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
        picker.peoplePickerDelegate = self;
        NSArray *displayedItems = [NSArray arrayWithObjects:[NSNumber numberWithInt:kABPersonPhoneProperty], 
                                   [NSNumber numberWithInt:kABPersonEmailProperty],
                                   [NSNumber numberWithInt:kABPersonBirthdayProperty], nil];
        picker.displayedProperties = displayedItems;
        // Show the picker 
        [self presentModalViewController:picker animated:YES];
    }
    

    The result:

    picker http://i.minus.com/jeEVeIBmfIYdR.png

    It is not clear to me why the People picker does not show.

    3 Solutions Collect From Internet About “Display ABPeoplePickerNavigationController using storyboard segue”

    Besi’s answer is great. But it’s less code to just use the old way instead of using a storyboard for it:

    - (void)showPeoplePicker:(id)sender
    {
        ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init];
        picker.peoplePickerDelegate = self;
        picker.modalPresentationStyle = UIModalPresentationFullScreen;
        picker.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
        [self presentViewController:picker
                           animated:YES                     
                         completion:^{
                         // animation to show view controller has completed.
                         }];
    }
    

    Curiously what I suggested on Can I use segues with designated initializers of view controllers? fixed the issue for me as well. So creating a proxy ViewController for the ABPeoplePickerNavigationController fixes the issue, but it does not explain, why the built-in pickers can’t be used in storyboards:

    This is the code for my wrapper class:

    #import "PeoplePickerViewControllerWrapper.h"
    
    @implementation PeoplePickerViewControllerWrapper
    
    @synthesize ppvc = _ppvc;  // This is the object I'm proxying (The proxyee so to speak)
    @synthesize delegate = _delegate;
    
    - (void)awakeFromNib
    {
            self.ppvc = [[ABPeoplePickerNavigationController alloc] init ];
            self.ppvc.peoplePickerDelegate = self;
            self.ppvc.addressBook = ABAddressBookCreate(); 
            self.ppvc.displayedProperties = [NSArray arrayWithObject:[NSNumber numberWithInt:kABPersonPhoneProperty]];
    }
    
    #pragma mark - View lifecycle
    
    - (void)loadView
    {
        [super loadView];
        [self.ppvc loadView];
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self.ppvc viewDidLoad];
    }
    
    -(void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        [self.ppvc viewWillAppear:animated];
    }
    
    -(void)viewDidDisappear:(BOOL)animated{
        [super viewDidDisappear:animated];
        [self.ppvc viewDidDisappear:animated];
    }
    
    -(UIView *)view{
        return self.ppvc.view;
    }
    
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        [self.ppvc viewDidUnload];
    }
    

    As Matt noted the good old way is ok. If you want to use storyboard you can add ABPeoplePickerNavigationController in your customized view controller like this:

    - (void)awakeFromNib
    {    
        ABPeoplePickerNavigationController * peoplePicker = [[ABPeoplePickerNavigationController alloc] init];
        peoplePicker.peoplePickerDelegate = self;
        // Display only a person's phone and address
        NSArray * displayedItems = [NSArray arrayWithObjects:[NSNumber numberWithInt:kABPersonAddressProperty],
                                [NSNumber numberWithInt:kABPersonPhoneProperty],
                                nil];
    
        peoplePicker.displayedProperties = displayedItems;
    
        [self.view addSubview:peoplePicker.view];
        [self addChildViewController:peoplePicker];
        [peoplePicker didMoveToParentViewController:self];    
    }