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:
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.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.
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.