Search code examples
iosobjective-cios8contacts

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?


Solution

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