Display ABPeoplePickerNavigationController using s

2019-02-13 09:53发布

问题:

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.

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.

回答1:

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.
                     }];
}


回答2:

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];
}


回答3:

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];    
}