0

I get EXC_BAD_ACCESS problem either while getting birthday or email for random people variable. I tried using the following code which fails when I run it using dispatch_async.

ABAddressBook addressBook = ABAddressBookCreateWithOptions(NULL, error);

CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
int maxThreads = 8;
int chunkSize = (int)(nPeople/maxThreads);

for (int loopNum = 0; loopNum < maxThreads; loopNum++)
{
    int initCondition = chunkSize*loopNum;
    int termCondition = (loopNum==(maxThreads-1)) ? (int)nPeople : chunkSize*(loopNum+1);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=initCondition; i<termCondition; i++)
        {
            @try {
                ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);

                NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty)) ? (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty)) : @"";
                NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty)) ? (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty)) :@"";

                NSString *birthDate = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonBirthdayProperty));

                ABMultiValueRef emailMultiValue = ABRecordCopyValue(person, kABPersonEmailProperty);
                NSArray *emailAddresses = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue);

                ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);

                NSMutableArray *numbers = [NSMutableArray arrayWithCapacity:ABMultiValueGetCount(phoneNumbers)];
                for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++)
                {
                    NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
                    phoneNumber = [self removeSpecialChars:phoneNumber];
                    if ([phoneNumber length] >= 8)
                    {
                        NSString *mobileNumber = [self getPhoneNuber:phoneNumber];;
                        if ([mobileNumber length] > 7 && [mobileNumber length] < 11)
                            [numbers addObject:mobileNumber];
                    }
                }
                NSString *mobileNumbers = [numbers componentsJoinedByString:@","];
            }
            @catch (NSException *exception)
            {
                NSLog(@"%@", exception);
            }
        }
    });
}

When I run the code without dispatch_async block, it runs without error. I want to do it with dispatch_async block to scan address book in parallel and detect any change from local database.

meteors
  • 1,747
  • 3
  • 20
  • 40

1 Answers1

2

In the documentation for ABAddressBookRef it states that these objects must be created and used on only one thread. Your code appears to create the ABAddressBook and the AVRecordRefs on the original thread, and then access them from the dispatch_async blocks. I would recommend finding another way to do this, where you create the ABAddressBook and the AVRecordRefs "just in time" on the background thread.

Another question also has some more relevant information...

Community
  • 1
  • 1
ipmcc
  • 29,581
  • 5
  • 84
  • 147
  • Thanks @ipmcc. But do you any solution to how to scan address book quickly with local contacts and find new contact info? – meteors May 14 '15 at 12:53
  • Not specifically. That sounds like a different issue. I would suggest you create a separate question. – ipmcc May 14 '15 at 13:33