Some of our app store users are reporting a crash while searching their address book.
I’m pretty lost here cause I can’t reproduce this issue.

Is there anything wrong with how I’m querying the address book ? Thanks!!
+ (NSDictionary *) scanAddressBook
{
#if TARGET_OS_IPHONE
NSUInteger i;
CFIndex index;
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *people = (NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook);
if ( people==nil || (people && ([people count] == 0)))
{
TRACE_LOG(@"scanAddressBook ", @"NO ADDRESS BOOK ENTRIES TO SCAN");
if(people) [people release];
CFRelease(addressBook);
return nil;
}
NSMutableArray *numbersArray = [NSMutableArray new];
NSMutableArray *mailsArray = [NSMutableArray new];
for ( i=0; i<[people count]; i++ )
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
ABRecordRef person = (ABRecordRef)[people objectAtIndex:i];
NSMutableDictionary *phoneDictionary = [NSMutableDictionary new];
CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString* log =[NSString stringWithFormat:@"-----CONTACT ENTRY -> %@ : %@", firstName, lastName ];
TRACE_LOG(@"scanAddressBook",log);
NSString *userName = @"NoName";
if (firstName && lastName)
userName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
else if (firstName)
userName = [NSString stringWithFormat:@"%@", firstName];
else if (lastName)
userName = [NSString stringWithFormat:@"%@", lastName];
if(firstName) CFRelease(firstName);
if(lastName) CFRelease(lastName);
//
// Phone Numbers
//
ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phoneNumberCount = ABMultiValueGetCount( phoneNumbers );
for ( index=0; index<phoneNumberCount; index++ )
{
CFStringRef phoneNumberLabel = ABMultiValueCopyLabelAtIndex( phoneNumbers, index);
CFStringRef phoneNumberValue = ABMultiValueCopyValueAtIndex( phoneNumbers, index);
CFStringRef phoneNumberLocalizedLabel = ABAddressBookCopyLocalizedLabel( phoneNumberLabel );
// converts "_$!<Work>!$_" to "work" and "_$!<Mobile>!$_" to "mobile"
// Find the ones you want here
//
NSString* log =[NSString stringWithFormat:@"-----PHONE ENTRY -> %@ : %@", phoneNumberLocalizedLabel, phoneNumberValue ];
TRACE_LOG(@"scanAddressBook",log);
if (![NetworkingUtils validatePhoneNumber:(NSString *)phoneNumberValue]) {
NSLog(@"invalid phone number: %@",phoneNumberValue);
CFRelease(phoneNumberLocalizedLabel);
CFRelease(phoneNumberLabel);
CFRelease(phoneNumberValue);
continue;
}
[phoneDictionary setObject:(NSString *)phoneNumberValue forKey:InviteUserDataNumberKeyID];
[phoneDictionary setObject:(NSString *)phoneNumberLocalizedLabel forKey:InviteUserDataNumberTypeKeyID];
[phoneDictionary setObject:(NSString *)userName forKey:InviteUserDataNameTypeKeyID];
CFRelease(phoneNumberLocalizedLabel);
CFRelease(phoneNumberLabel);
CFRelease(phoneNumberValue);
NSMutableDictionary *copyPhoneDict = [phoneDictionary copy];
[numbersArray addObject:copyPhoneDict];
[copyPhoneDict release];
}
CFRelease(phoneNumbers);
[phoneDictionary release];
NSMutableDictionary *mailDictionary = [NSMutableDictionary new];
ABMutableMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
CFIndex mailsNumberCount = ABMultiValueGetCount( emails );
for ( index=0; index < mailsNumberCount; index++ )
{
CFStringRef emailValue = ABMultiValueCopyValueAtIndex( emails,index);
// converts "_$!<Work>!$_" to "work" and "_$!<Mobile>!$_" to "mobile"
// Find the ones you want here
//
NSString* log =[NSString stringWithFormat:@"-----EMAIL ENTRY -> : %@", emailValue ];
TRACE_LOG(@"scanAddressBook",log);
if (![NetworkingUtils validateEmail:(NSString *)emailValue]) {
NSLog(@"invalid email address: %@",(NSString *)emailValue);
if (emailValue) {
CFRelease(emailValue);
}
continue;
}
[mailDictionary setObject:(NSString *)emailValue forKey:InviteUserDataMailKeyID];
[mailDictionary setObject:(NSString *)@"email" forKey:InviteUserDataMailTypeKeyID];
[mailDictionary setObject:(NSString *)userName forKey:InviteUserDataMailOwnerKeyID];
if (emailValue) {
CFRelease(emailValue);
}
NSMutableDictionary *copyMailDict = [mailDictionary copy];
[mailsArray addObject:copyMailDict];
[copyMailDict release];
}
if(emails) CFRelease(emails);
[mailDictionary release];
[pool drain];
}
NSString *countryCode = [[NSUserDefaults standardUserDefaults] objectForKey:RequestUserCountryCodeKeyID];
if (!countryCode) {
NSLocale *locale = [NSLocale currentLocale];
NSString *aCode = [locale objectForKey: NSLocaleCountryCode];
countryCode = [[NetworkingUtils codesByCountryCode] objectForKey:aCode];
}
NSDictionary *aDictionary = [NSDictionary dictionaryWithObjectsAndKeys: [[numbersArray copy] autorelease], InviteUsersNumbersArrayKeyID,
[[mailsArray copy] autorelease], InviteUsersMailsArrayKeyID,
countryCode, RequestUserCountryCodeKeyID, nil];
[numbersArray release];
[mailsArray release];
[people release];
CFRelease(addressBook);
return aDictionary;
#else
return nil ;
#endif
}
CFRelease()will crash if you provide aNULLvalue. I see most of yourCFRelease()calls do check forNULL, but not all of them.Most likely one of these is triggering the crash?
I’m not very familiar with
ABAddressBook, so don’t know in what situations they would returnNULL.On a related note, Objective-C’s
-releasemethod does not crash onnil, so you may as well change:if(people) [people release];to just[people release];as all methods in Objective-C will silently do nothing if sent to anil.