dormitkon dormitkon - 4 months ago 20
iOS Question

Get contacts list in iOS8, crashes the app

Getting contacts in iOS8 (iPhone 5s) causes crash randomly.
Crash details: http://hastebin.com/ukihinucaf.md

At line:

ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);


Here is the whole function:

-(NSArray *) getAllContacts
{

CFErrorRef *error = nil;

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

}
else {
accessGranted = YES;
}

if (accessGranted) {

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];
for (int i = 0; i < nPeople; i++)
{

ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);

//get Contact email

ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);

for (CFIndex j=0; j<ABMultiValueGetCount(multiEmails); j++) {
CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, j);
NSString *contactEmail = (__bridge NSString *)contactEmailRef;

[items addObject:contactEmail];
}

}
return items;

} else {
NSLog(@"Cannot fetch Contacts :( ");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Fetch failed" message:@"Can't fetch your contacts." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
return nil;

}
}


Anybody knows what can be a problem?

Rob Rob
Answer

You are retrieving ABAddressBookGetPersonCount (the count of all the people in all of the sources, not just the count of people in the default source), and using that as the upper threshold when you're iterating through the array. But the array doesn't contain all of the people in the address book, but rather only those in the default source. Thus, you may exceed the number of items in the array.

I would suggest using CFArrayGetCount rather than ABAddressBookGetPersonCount.

Comments