ios8abaddressbookabpersonviewcontroller

iOS8 bugs: ABPersonViewController does not display properties & back button


The following code works correctly in iOS7, but not in iOS8 (the variable recordID is set correctly):

    CFErrorRef error = nil;
    const ABAddressBookRef addressBook = (ABAddressBookCreateWithOptions (NULL, &error));
    ABRecordRef contactRef = ABAddressBookGetPersonWithRecordID (addressBook, recordID);
    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
    personViewController.addressBook     = addressBook;
    personViewController.displayedPerson = contactRef;
    CFRelease(addressBook);
    NSArray *displayedProperties = @[@(kABPersonFirstNameProperty),
                                     @(kABPersonLastNameProperty),
                                     @(kABPersonMiddleNameProperty),
                                     @(kABPersonPrefixProperty),
                                     @(kABPersonSuffixProperty),
                                     @(kABPersonOrganizationProperty),
                                     @(kABPersonJobTitleProperty),
                                     @(kABPersonDepartmentProperty),
                                     @(kABPersonEmailProperty),
                                     @(kABPersonBirthdayProperty),
                                     @(kABPersonKindProperty),
                                     @(kABPersonAddressProperty),
                                     @(kABPersonPhoneProperty),
                                     @(kABPersonInstantMessageProperty),
                                     @(kABPersonURLProperty),
                                     @(kABPersonSocialProfileProperty),
                                     @(kABPersonNoteProperty)];
    personViewController.displayedProperties  = displayedProperties;
    personViewController.navigationItem.title = NSLocalizedString(@"CONTACT_DETAILS", nil);
    personViewController.allowsActions        = YES;
    personViewController.allowsEditing        = YES; // if NO, no back button is shown
    personViewController.personViewDelegate   = self;
    personViewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"ADDRESSES",nil) style:UIBarButtonItemStylePlain target:self action:@selector(personviewDoneButtonPressed:)];

    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:personViewController];
    [self presentViewController:navigationController animated:YES completion:nil];

Bugs in iOS8:

  1. When allowsEditing is set to YES, the contact is shown, but only the name is displayed. The navigation bar shows left the back button (named "Addresses") and right the edit button. When the edit button is pressed, the contact is displayed with all fields empty except the name, and the edit button is displayed as a done button. If this done button is pressed without any editing before, all information about the contact is displayed.
  2. When allowsEditing is set to NO, no back button is shown, so that the screen can no longer be left.

Has anybody a workaround?

UPDATE:

I realized by now, that problem 1 only sometimes occurs on the simulator, although always on my device.


Solution

  • montuno (thanks again), who commented my first answer, got a hint from Apple technical support how to solve the 1st problem, and I understand now also the 2nd problem:

    1) Only part of the contact displayed:

    Apple claimed that the following code is wrong:

    ABRecordRef contactRef = ABAddressBookGetPersonWithRecordID (addressBook, recordID);
    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
    personViewController.addressBook     = addressBook;
    personViewController.displayedPerson = contactRef;
    CFRelease(addressBook);
    

    Here addressBook is erroneously released, after it has been assigned to the ABPersonViewController.

    In my original code, I did not have the CFRelease statement. But then the static analyzer warned of a „Potential leak of an object stored in addressBook“. After I inserted the release statement, the build succeeded without warning, so I assumed that the personViewController retained the addressBook, which is apparently not the case, at least not with iOS8. I removed now the release statement again, got the warning back, but everything works fine.

    2) Missing back button:
    The docs of the ABPersonViewController say „IMPORTANT Person view controllers must be used with a navigation controller in order to function properly.

    So what I did was the following:
    I set up an ABPersonViewController, assigned to its navigationItem.backBarButtonItem a „Done“ button, and initialized a new UINavigationController with this personViewController, using initWithRootViewController:. Then I presented the new navigationController modally.
    The personViewController with the back button was displayed, and when pressed, the presenting view controller dismissed the modally presented navigation controller.
    This worked fine on iOS < 8, but in iOS8, the back button was not displayed, when allowsEditing was set to NO.

    But this is apparently not how Apple wants to display the personViewController:
    I think Apple assumes that a navigationController already exists, and presents the current view, so that a new personViewController is just pushed onto the stack of the navigationController. In this case, the personViewController is not the rootViewController of the navigationController, and the navigationController displays automatically a back button (which is not done for the rootViewController). If implemented this way, everything works fine also for iOS8.