Reputation: 37985
Update:
I believe the problem lies somewhere in how I am storing the reference to ABRecordRef
. I am currently just hanging onto the value as delivered to peoplePickerNavigationController:shouldContinueAfterSelectingPerson:property:identifier:
and not CFRetain
ing it or anything. It's unclear from the documentation if it needs to be retained.
I'm working on an iPhone app and it interfaces with the address book using the AddressBook and AddressBookUI frameworks. I'm using the ABPeoplePickerNavigationController
to present a contact list to the user to choose, and am capturing the resultant ABRecordRef
as an instance variable on a custom class.
This is all working fine on the first use. However, the second time I pick someone from the contacts (even a different person), my app blows up with EXC_BAD_ACCESS
on a call to ABRecordCopyValue
. I am logging the pointers and they are definitely different each time a contact is selected (even if the same contact twice).
I fail to understand how this reference could be deallocated. A memory leak sure, but why does it work fine the first time and not the second?
Here's the actual call it's dying on:
- (NSString*)displayName {
return CFBridgingRelease( ABRecordCopyValue( self.contact, kABPersonFirstNameProperty ) );
}
Here's some debug output if it's helpful at all:
Printing description of self->_contact:
(ABRecordRef) _contact = 0x1f582dc0
(lldb) expr (CFTypeRef)ABRecordCopyValue(self.contact, kABPersonFirstNameProperty)
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xd1f57cc1).
The process has been returned to the state before execution.
Upvotes: 1
Views: 239
Reputation: 37985
Turns out all I needed was to CFRetain( person )
and everything's happy go lucky again. I also added a dealloc
to my class to clean up the pointer when the object goes away:
- (void)dealloc {
CFRelease( _contact );
}
My code now runs smoothly and the static analyser is happy (not that it caught the leak anyway).
Upvotes: 1
Reputation: 19946
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
[self displayPerson:person];
[self dismissViewControllerAnimated:YES completion:nil];
return NO;
}
you returning NO ?
Try checking to see if the value exists maybe
ie
- (void)displayPerson:(ABRecordRef)person
{
NSString* companyName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty);
NSString* name = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString* display = @"";
if (companyName) {
display = companyName;
} else if (name) {
display = name;
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"No Details For Contact"
message:@"Please update contact with company and/or first name"
delegate:nil
cancelButtonTitle:@"Dismiss"
otherButtonTitles:nil];
[alertView show];
}
}
Upvotes: 0