Please find below a code to import the iOS address book (lets assume we need to import - not just get a handle to it, for a specific need) --> some people using the app are complaining that only 15-20 of their addresses are being imported out of say 500. When one such person sent us their address book, I noticed besides 15-20 others are tagged as iCloud. This problem is not happening with everyone. Can someone tell us if we need to add special code for iCloud tagged entries? I don't think so, but confirming
- (void)getPersonOutOfAddressBook
{
CFErrorRef error = NULL;
__block BOOL accessGranted = NO;
isAddressBookAccessGranted=NO;
ABAddressBookRef addressBook = nil;
addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (ABAddressBookRequestAccessWithCompletion != NULL)
{
//-- we're on iOS 6
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (!granted)
{
isAddressBookAccessGranted = NO;
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"ERROR", nil) message:NSLocalizedString(@"ENABLE CONTACT ACCESS MESSAGE", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil, nil];
[alertView performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];
}
else
{
isAddressBookAccessGranted = YES;
[self loadAddressBook:addressBook];
}
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
isAddressBookAccessGranted = YES;
{
[self loadAddressBook:addressBook];
}
}
else if(ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusDenied)
{
isAddressBookAccessGranted = NO;
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"ERROR", nil) message:NSLocalizedString(@"ENABLE CONTACT ACCESS MESSAGE", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil, nil];
[alertView show];
// deleted some other code here - not related to addr book
}
else
{
//deleted some other code here - not related to addr book
}
}
else
{
//-- we're on iOS 5 or older
accessGranted = YES;
isAddressBookAccessGranted = YES;
[self loadAddressBook:addressBook];
}
}
-(void) loadAddressBook:( ABAddressBookRef)currAddressBook
{
if (currAddressBook != nil)
{
ABRecordRef source = ABAddressBookCopyDefaultSource(currAddressBook);
NSArray *allContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(currAddressBook, source, kABPersonSortByFirstName);
NSUInteger i = 0;
// if([AppDelegate sharedInstance].ABContactsArray!=nil)
[mTempContactsArray removeAllObjects];
for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[[Person alloc] init] autorelease];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
int recordID = ABRecordGetRecordID(contactPerson);
person.recordID=[NSString stringWithFormat:@"%d",recordID];
NSLog(@"RecordID = %d\n", recordID);
NSString *firstName = ( NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSLog(@"firstName = %@\n", firstName);
NSString *lastName = ( NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSLog(@"lastName = %@\n", lastName);
NSString *fullName;
if(!(firstName==nil) && !(lastName==nil))
fullName= [NSString stringWithFormat:@"%@ %@", firstName, lastName];
else if((firstName==nil) && (lastName==nil))
fullName = @"";//[NSString stringWithFormat:NSLocalizedString(@"NO NAME STORED", nil)];
else if (firstName==nil)
fullName=[NSString stringWithFormat:@"%@", lastName];
else if(lastName==nil)
fullName=[NSString stringWithFormat:@"%@", firstName];
person.firstName = firstName;
person.lastName = lastName;
person.fullName = fullName;
person.imageData = ( NSData *) ABPersonCopyImageDataWithFormat(contactPerson, kABPersonImageFormatThumbnail);
NSLog(@"imageData = %@\n", person.imageData);
ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
NSUInteger count=0;
NSUInteger j = 0;
person.numberDetailArray = [[[NSMutableArray alloc]init] autorelease] ;
for (j = 0; j < ABMultiValueGetCount(phones); j++)
{
NSString *contactCategory;
NSString *phone = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phones, j);
NSLog(@"phone number = %@\n", phone);
NSString *phoneLabel = (__bridge NSString *) ABMultiValueCopyLabelAtIndex(phones, j);
NSLog(@"phoneLabel = %@\n", phoneLabel);
if([phoneLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
{
contactCategory = @"mobile";
count++;
}
else if([phoneLabel isEqualToString:(NSString *)kABPersonPhoneIPhoneLabel])
{
contactCategory = @"iPhone";
count++;
}
else if([phoneLabel isEqualToString:(NSString *)kABPersonPhoneMainLabel])
{
contactCategory = @"main";
count++;
}
else if ([phoneLabel isEqualToString:@"_$!<Home>!$_"])
{
contactCategory = @"home";
count++;
}
else if ([phoneLabel isEqualToString:@"_$!<Work>!$_"])
{
contactCategory = @"work";
count++;
}
else
{
contactCategory = @"other";
count++;
}
NumberInfo *numberInfo = [[[NumberInfo alloc]init] autorelease];
numberInfo.contactNumberCategory = contactCategory;
numberInfo.contactNumber = phone;
numberInfo.parentID = person.recordID;
//numberInfo.recordType = [NSNumber numberWithInt:kNumberRecord];
[person.numberDetailArray addObject:numberInfo];
if(phone)
CFRelease((__bridge CFTypeRef)(phone));
if(phoneLabel)
CFRelease((__bridge CFStringRef)(phoneLabel));
}
person.phoneNumberCount= [NSString stringWithFormat:@"%d",(int)count];
[mTempContactsArray addObject:person];
if(phones)
CFRelease(phones);
}
if(source)
CFRelease(source);
NSLog(@"count=%d",[mTempContactsArray count]) ;
}
//-- after loading all the contacts, perform the table view operations on main thread
// [self performSelectorOnMainThread:@selector(initializeSharedContactList) withObject:nil waitUntilDone:YES];
}
You need to iterate over all address book sources, not just the default one. Use ABAddressBookCopyArrayOfAllSources
to get all sources, then iterate all sources and get contacts using ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering
.