Search code examples
iosobjective-caddressbookabaddressbook

ABAddressBookCreateWithOptions causes crash (unrecognized selector)


In my iPad app (Xcode 5, iOS 7, ARC, Storyboards), I'm trying to read the Address book and get all of the entries. Unfortunately, I get the following error:

SalonBook[2225:a0b] -[__NSCFString count]: unrecognized selector sent to instance 0xb335e70

This is my code that I copied from SO (why re-invent the wheel?).

-(IBAction)importClientData:(UIButton *)sender {

NSMutableArray *allContacts = [[NSMutableArray alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
CFArrayRef people  = ABAddressBookCopyArrayOfAllPeople(addressBook);
for(int i = 0;i<ABAddressBookGetPersonCount(addressBook);i++)
{
    NSMutableDictionary *aPersonDict = [[NSMutableDictionary alloc] init];
    ABRecordRef ref = CFArrayGetValueAtIndex(people, i);
    NSString *fullName = (__bridge NSString *) ABRecordCopyCompositeName(ref);
    if (fullName) {
        [aPersonDict setObject:fullName forKey:@"fullName"];

        // collect phone numbers
        NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
        ABMultiValueRef phones = ABRecordCopyValue(ref, kABPersonPhoneProperty);
        for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++) {
            NSString *phoneNumber = (__bridge NSString *) ABMultiValueCopyValueAtIndex(phones, j);
            [phoneNumbers addObject:phoneNumber];
        }
        [aPersonDict setObject:phoneNumbers forKey:@"phoneNumbers"];

        // collect emails - key "emails" will contain an array of email addresses
        ABMultiValueRef emails = ABRecordCopyValue(ref, kABPersonEmailProperty);
        NSMutableArray *emailAddresses = [[NSMutableArray alloc] init];
        for(CFIndex idx = 0; idx < ABMultiValueGetCount(emails); idx++) {
            NSString *email = (__bridge NSString *)ABMultiValueCopyValueAtIndex(emails, idx);
            [emailAddresses addObject:email];
        }
        [aPersonDict setObject:emailAddresses forKey:@"emails"];
        // if you want to collect any other info that's stored in the address book, it follows the same pattern.
        // you just need the right kABPerson.... property.

        [allContacts addObject:aPersonDict];
    }
    else {
        // Note: I have a few entries in my phone that don't have a name set
        // Example one could have just an email address in their address book.
    }
}

}

UPDATE: Here is the complete stack trace:

0 CoreFoundation 0x2e335f53 + 130
1 libobjc.A.dylib 0x3899e6af objc_exception_throw + 38
2 CoreFoundation 0x2e3398e7 + 202
3 CoreFoundation 0x2e3381d3 + 706
4 CoreFoundation 0x2e287598 _CF_forwarding_prep_0 + 24
5 AddressBook 0x2d9274fd ABCCopyUserLanguage + 60
6 AddressBook 0x2d914e3d ABCIsSortDataValid + 28
7 AddressBook 0x2d914d6d ABCCreateAddressBookWithDatabaseDirectoryAndForceInProcessMigrationInProcessLinkingAndResetSortKeys + 1120
8 AddressBook 0x2d928d17 ABAddressBookCreateWithDatabaseDirectory + 74
9 AddressBook 0x2d928e67 ABAddressBookCreateWithOptionsAndPolicy + 146
10 AddressBook 0x2d9290c9 ABAddressBookCreateWithOptions + 88
11 SalonBook 0x000e35db -[CustomerSetupController importClientData:] + 118
12 UIKit 0x30adbf3f + 90
13 UIKit 0x30adbedf + 30
14 UIKit 0x30adbeb9 + 44
15 UIKit 0x30ac7b3f + 374
16 UIKit 0x30adb92f + 590
17 UIKit 0x30adb601 + 528
18 UIKit 0x30ad668d + 832
19 UIKit 0x30aaba25 + 196
20 UIKit 0x30aaa221 + 7096
21 CoreFoundation 0x2e30118b + 14
22 CoreFoundation 0x2e30065b + 206
23 CoreFoundation 0x2e2fee4f + 622
24 CoreFoundation 0x2e269ce7 CFRunLoopRunSpecific + 522
25 CoreFoundation 0x2e269acb CFRunLoopRunInMode + 106
26 GraphicsServices 0x32f37283 GSEventRunModal + 138
27 UIKit 0x30b0ba41 UIApplicationMain + 1136
28 SalonBook 0x000b6335 main + 116
29 libdyld.dylib 0x38ea6ab7 + 2

No matter what code I use (I have tried several variations of the above code) they all crash on the same call (-ABAddressBookCreateWithOptions). Since I copied the same code from multiple examples, I would expect at least this line to work. It's not! Why?


Solution

  • It is not clear whether or not you are calling ABAddressBookRequestWithCompletion to obtain the user's permission to access the address book. If you don't do this on an app targeting iOS 6 or newer, you will not be allowed to access the address book. That being said, AddressBook API should not crash in this way. You may need to report a bug to apple via bugreport.apple.com.