IOS8 errors: ABPersonViewController not displaying properties and back button

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

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;
    NSArray *displayedProperties = @[@(kABPersonFirstNameProperty),
    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];


Errors in iOS8:

  • If the parameter is allowsEditing

    set to a value YES

    , the contact is displayed, but only the name is displayed . The navigation bar displays a Back button (named Addresses) and to the right of the edit button. When the edit button is clicked, the contact is displayed with all fields blank except the name , and the edit button is displayed as a made button. If this button is pressed without any editing, all contact information is displayed .
  • If the parameter is allowsEditing

    set to a value NO

    , the back button is not displayed so that the screen can no longer remain.

Does anyone have a workaround?


I realized that on the simulet sometimes only 1 sometimes , although always on my device >.


source to share

2 answers

montuno (thanks again) who commented on my first answer got a hint from Apple tech support how to fix the first problem and now I understand the second problem too:

1) Only part of the displayed contact is displayed:

Apple stated that the following code is incorrect:

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


Here is addressBook

erroneously released after he was appointed ABPersonViewController


In my original code, I didn't have an operator CFRelease

. But then the static analyzer warned about "a potential leak of an object stored in the address book." After I inserted the release statement, the build went through without warning, so I assumed I personViewController

kept it addressBook

, which is apparently not the case, at least not with iOS8. I removed the release statement again, got a warning, but everything works fine.

2) Missing back button:
The docs ABPersonViewController

say "IMPORTANT Person view controllers must be used with a navigation controller to work properly."

So what I did is this:
I installed ABPersonViewController

assigned to its navigationItem.backBarButtonItem

a "Done" button and initialized a new one UINavigationController

with that personViewController

using initWithRootViewController:

. Then I introduced a new navigationController

A personViewController

back button appeared and when clicked, the view controller rendered the rejected navigation controller. This worked fine on iOS 8, but in iOS8 the back button was not displayed when allowsEditing

set to NO


But that doesn't seem to be how Apple wants to display personViewController

I think Apple assumes that it navigationController

already exists and represents the current view, so a new one is personViewController

simply pushed onto the stack navigationController

. In this case, it personViewController

does not rootViewController


, but navigationController

automatically displays a return button (which is not executed for rootViewController

). If you implement this method, everything works fine for iOS8 as well.



UPDATE: This hack no longer works and is completely useless (see my new answer)

In case anyone has the same problem 1) above, here is a really dirty workaround until Apple fixes the bug (my bug reports are still open):
Since it is required to toggle the edit button twice after displaying the screen in some situations ABPersonViewController

, this is can be done programmatically:

Define a property for UINavigationController

that represents ABPersoViewController


@property (nonatomic, strong) UINavigationController *  navigationControllerForPersonViewController;


After the navigation controller presents the face view controller, execute the selector to perform the toggle:

[self performSelector:@selector(toggleEditButton) withObject:nil afterDelay:0.7];  


The delay is set so that the human view manager screen can be displayed with animation. The method is toggleEditButton

defined as:

- (void)toggleEditButton
    UIBarButtonItem *editButton  = self.navigationControllerForPersonViewController.topViewController.navigationItem.rightBarButtonItem;
    id target =;
    SEL editAction = editButton.action;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [target performSelector:editAction withObject:editButton];
    [target performSelector:editAction withObject:editButton];
#pragma clang diagnostic pop


#pragmas are needed to suppress compiler warnings for potential memory leaks.
This will display all of the selected Human View Manager information.



All Articles