iosuiviewcontrollerabpeoplepickerview

App crash on use of PeoplePicker, but not in same view


Update 2, I hope this helps someone, there is a solutions at the following link: https://discussions.apple.com/thread/5498630?start=0&tstart=0 , evidently this is an iOS bug and this work around works. I can create the new sharedPicker, but I cannot get anything from it or dismiss it, I'm not sure how to format beyond what is supplied at the link Any help on that is very welcome.

So my question now is how to take the following code and actually create the code for peoplePickerNavigationControllerDidCancel: and peoplePickerNavigationController:shouldContinueAfterSelectingPerson: Thanks. I've left most of my original post in case someone has a similar vague issue.

// Convoluted workaround for the iPhone 4S crash
+ (ABPeoplePickerNavigationController *)sharedPeoplePicker {
    static ABPeoplePickerNavigationController *_sharedPicker = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedPicker = [[ABPeoplePickerNavigationController alloc] init];
    });
    return _sharedPicker;
}
// then later on, use 
[YourController sharedPeoplePicker].delegate = self;
// etc.

My current code:

- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier
{
    [self displayPerson:person];
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
    return NO;

}
- (void)peoplePickerNavigationControllerDidCancel:
(ABPeoplePickerNavigationController *)peoplePicker
{

    //[self dismissViewControllerAnimated:YES completion:nil];
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)pick1:(id)sender
{
    ABPeoplePickerNavigationController *picker1 =[[ABPeoplePickerNavigationController alloc] init];
    picker1.peoplePickerDelegate = self;

    [self presentViewController:picker1 animated:YES completion:nil];

    x=1;
}

Update 1, this app crashes on iPhone 4/4s, but runs in the simulator and iPhone5 if that means anything. I'm thinking its just they have enough power to get past whatever leak I have created

I have an iOS app with a view controller where the user can chose contacts for the app using ABPeoplePickerNavigationController or enter numbers manually. If numbers are entered manually there are no issues. If the user opens and:

  1. Picks a new contact from the address book

  2. Updates a contact from the address book to use in the app

  3. Opens and cancels the address book (all without saving the action)

Then I cannot navigate to one particular view in my app without a crash. I am at a loss why I cannot go to this one view controller, or why it causes the crash.

I am using 5 different pickers, one for each contact I want to add and potentially save. I save as NSUserDefaults, but like I said, the crash persists even if the picker selection is never saved. I can navigate to all view in the app from a sidebar navigation without incident, the only thing different about the view I fail on is that it is presented from one of the main view controllers and not my sidebar.

I appreciate any help or thoughts. This was the first app I wrote and I'm trying to update it and failing. I want to get it functional again so I can come back and refactor it.

My implementation:

    - (IBAction)pick1:(id)sender
{
    ABPeoplePickerNavigationController *picker1 =
    [[ABPeoplePickerNavigationController alloc] init];
    picker1.peoplePickerDelegate = self;

    [self presentViewController:picker1 animated:YES completion:nil];
    x = 1;
}
- (IBAction)pick2:(id)sender
{
    ABPeoplePickerNavigationController *picker2 =
    [[ABPeoplePickerNavigationController alloc] init];
    picker2.peoplePickerDelegate = self;

    [self presentViewController:picker2 animated:YES completion:nil];
    x=2;
}
- (IBAction)pick3:(id)sender
{
    ABPeoplePickerNavigationController *picker3 =
    [[ABPeoplePickerNavigationController alloc] init];
    picker3.peoplePickerDelegate = self;

    [self presentViewController:picker3 animated:YES completion:nil];
    x=3;
}
- (IBAction)pick4:(id)sender
{
    ABPeoplePickerNavigationController *picker4 =
    [[ABPeoplePickerNavigationController alloc] init];
    picker4.peoplePickerDelegate = self;

    [self presentViewController:picker4 animated:YES completion:nil];
    x=4;
}
- (IBAction)pick5:(id)sender
{
    ABPeoplePickerNavigationController *picker5 =
    [[ABPeoplePickerNavigationController alloc] init];
    picker5.peoplePickerDelegate = self;

    [self presentViewController:picker5 animated:YES completion:nil];
    x=5;
}
- (void)peoplePickerNavigationControllerDidCancel:
(ABPeoplePickerNavigationController *)peoplePicker
{
    [self dismissViewControllerAnimated:YES completion:nil];
}


- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person {

    [self displayPerson:person];
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];


    return NO;
}

- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier
{
    return NO;
}
- (void)displayPerson:(ABRecordRef)person
{
    NSString* name = (__bridge_transfer NSString*)ABRecordCopyValue(person,
                                                                    kABPersonFirstNameProperty);


    NSString* phone = nil;
    ABMultiValueRef phoneNumbers = ABRecordCopyValue(person,
                                                     kABPersonPhoneProperty);
    if (ABMultiValueGetCount(phoneNumbers) > 0) {
        phone = (__bridge_transfer NSString*)
        ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
    } else {
        phone = @"[None]";
    }
    if (x==1){
        firstName1.text = name;
        contact1.text = phone;
    }
    if (x==2){
        firstName2.text = name;
        contact2.text = phone;
    }
    if (x==3){
        firstName3.text = name;
        contact3.text = phone;
    }
    if (x==4){
        firstName4.text = name;
        contact4.text = phone;
    }
    if (x==5){
        firstName5.text = name;
        contact5.text = phone;
    }

}

Solution

  • Sorry to answer my own question, but another work around to this that requires little change is to use CF Retain to correct the over release I was experiencing. I retained the person and the peoplePicker and all was resolved. Thanks for everyone who tried to help me solve this.

    - (void)peoplePickerNavigationControllerDidCancel:
    (ABPeoplePickerNavigationController *)peoplePicker
    {
    
        [self.navigationController dismissViewControllerAnimated:YES completion:nil];
       CFRetain((__bridge CFTypeRef)(peoplePicker));
    }
    - (BOOL)peoplePickerNavigationController:
    (ABPeoplePickerNavigationController *)peoplePicker
          shouldContinueAfterSelectingPerson:(ABRecordRef)person
                                    property:(ABPropertyID)property
                                  identifier:(ABMultiValueIdentifier)identifier
    {
        [self displayPerson:person];
        [self.navigationController dismissViewControllerAnimated:YES completion:nil];
        CFRetain(person);
        CFRetain((__bridge CFTypeRef)(peoplePicker));
        return NO;
    
    }