Is there any faster way to find a single number using ABAdressBook? - ios

How to find a single number from ABAdressBook which contains 10 000 contacts?
Currently I am using ABAddressBookRef. Is there an alternative method to reduce iterating?
My code snippet:
if([numberType intValue] == NUMBER_TYPE_EXTERNAL && [appDelegate isNativeContactAccess] == YES)
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(numberType == %#)",[NSNumber numberWithInt:NUMBER_TYPE_EXTERNAL]];
[fetchRequest setPredicate:predicate];
NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
/* The method ABAddressBookCreate() is deprecated in ios 6 so below method is used here */
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
for (NSInteger resultCnt=0; resultCnt<[results count]; resultCnt++)
{
Contact *contact = [results objectAtIndex:resultCnt];
ABRecordID r = [contact.indexValue intValue];
ABRecordRef fetchData = ABAddressBookGetPersonWithRecordID(addressBook, r);
if(fetchData != nil)
{
NSUInteger lengthOfSearchStr = [searchNumber length];
ABMultiValueRef multi = ABRecordCopyValue(fetchData, kABPersonPhoneProperty);
NSUInteger j=0;
for(j=0; j<ABMultiValueGetCount(multi); j++)
{
NSString *getNum = (NSString *)ABMultiValueCopyValueAtIndex(multi, j);
NSString *removedspecialchar6 = [getNum stringByReplacingOccurrencesOfString:#"[^0-9*+#]" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0,[getNum length])];
if(lengthOfSearchStr <= [removedspecialchar6 length])
{
number = [removedspecialchar6 substringFromIndex:[removedspecialchar6 length] - lengthOfSearchStr];
if([number isEqualToString:searchNumber])
{
[getNum release];
CFRelease(addressBook);
CFRelease(multi);
return contact;
}
}
[getNum release];
}
CFRelease(multi);
}
}
CFRelease(addressBook);
}

NSUInteger index;
NSUInteger findIndex;
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *constactsNo = (NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook);
if ( constactsNo ==nil )
{
CFRelease(addressBook);
return;
}
for ( index=0; index<[constactsNo count]; index++ )
{
ABRecordRef find = (ABRecordRef)[constactsNo objectAtIndex:index];
ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(find, kABPersonPhoneProperty);
CFIndex phoneNumberCount = ABMultiValueGetCount( phoneNumbers );
for ( findIndex =0; findIndex <phoneNumberCount; findIndex ++ )
{
CFStringRef phoneNumberLabel = ABMultiValueCopyLabelAtIndex( phoneNumbers, findIndex );
CFStringRef phoneNumberValue = ABMultiValueCopyValueAtIndex( phoneNumbers, findIndex );
CFStringRef phoneNumberLocalizedLabel = ABAddressBookCopyLocalizedLabel( phoneNumberLabel );
CFRelease(phoneNumberLocalizedLabel);
CFRelease(phoneNumberLabel);
CFRelease(phoneNumberValue);
}
}
[constactsNo release];
CFRelease(addressBook);

Related

Duplicate contact with ABAddressBook

I'm using ABAddressBook, I can display every contact, but I've some duplicate contact.
I've read this topic : Dealing with duplicate contacts due to linked cards in iOS' Address Book API, but can't fix the problem.
I would like to use this code in mine, but I don't succeed to.. :
NSMutableSet *unifiedRecordsSet = [NSMutableSet set];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(records); i++)
{
NSMutableSet *contactSet = [NSMutableSet set];
ABRecordRef record = CFArrayGetValueAtIndex(records, i);
[contactSet addObject:(__bridge id)record];
NSArray *linkedRecordsArray = (__bridge NSArray *)ABPersonCopyArrayOfAllLinkedPeople(record);
[contactSet addObjectsFromArray:linkedRecordsArray];
// Your own custom "unified record" class (or just an NSSet!)
DAUnifiedRecord *unifiedRecord = [[DAUnifiedRecord alloc] initWithRecords:contactSet];
[unifiedRecordsSet addObject:unifiedRecord];
CFRelease(record);
}
CFRelease(records);
CFRelease(addressBook);
_unifiedRecords = [unifiedRecordsSet allObjects];
Here is my code :
- (void)getPersonOutOfAddressBook
{
//1
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (addressBook != nil) {
NSLog(#"Succesful.");
//2
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
//3
NSUInteger i = 0; for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[Person alloc] init];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
//4
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson,
kABPersonFirstNameProperty);
if (firstName == nil)
{
firstName = #"";
}
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
if (lastName == nil)
{
lastName = #"";
}
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
person.firstName = firstName; person.lastName = lastName;
person.fullName = fullName;
//phone
//5
ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
//6
NSUInteger j = 0;
for (j = 0; j < ABMultiValueGetCount(phones); j++) {
NSString *phone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, j);
if (j == 0) {
person.mainNumber = phone;
}
else if (j==1) person.secondNumber = phone;
}
//7
[person.mainNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
[person.mainNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
[person.mainNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
[person.mainNumber stringByReplacingOccurrencesOfString:#"+336" withString:#"06"];
[self.tableData addObject:person];
[self.contact addObject:person.fullName];
}
//8
CFRelease(addressBook);
} else {
//9
NSLog(#"Error reading Address Book");
}
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:#"fullName" ascending:YES];
[self.tableData sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
}
If you want to avoid adding duplicates, it's probably easiest to build a set of the ABRecordID values that have already had something added, and only add a contact if it doesn't exist in that set already:
self.tableData = [NSMutableArray array];
NSMutableSet *foundIDs = [NSMutableSet set];
NSArray *allContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
for (id record in allContacts) {
ABRecordRef contactPerson = (__bridge ABRecordRef)record;
ABRecordID recordId = ABRecordGetRecordID(contactPerson);
if (![foundIDs containsObject:#(recordId)]) {
Person *person = [[Person alloc] init];
// get name
person.firstName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty)) ?: #"";
person.lastName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonLastNameProperty)) ?: #"";
person.fullName = [NSString stringWithFormat:#"%# %#", person.firstName, person.lastName];
// get phones
ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
for (NSUInteger j = 0; j < ABMultiValueGetCount(phones); j++) {
// I presume you meant to use mutable string and `replaceOccurrencesOfString`:
NSMutableString *phone = [CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, j)) mutableCopy];
[phone replaceOccurrencesOfString:#" " withString:#"" options:0 range:NSMakeRange(0, phone.length)];
[phone replaceOccurrencesOfString:#"(" withString:#"" options:0 range:NSMakeRange(0, phone.length)];
[phone replaceOccurrencesOfString:#")" withString:#"" options:0 range:NSMakeRange(0, phone.length)];
[phone replaceOccurrencesOfString:#"+336" withString:#"06" options:0 range:NSMakeRange(0, phone.length)];
if (j == 0) person.mainNumber = phone;
else if (j==1) person.secondNumber = phone;
}
CFRelease(phones);
// add the `Person` record
[self.tableData addObject:person];
// add the ID for this person (and all linked contacts) to our set of `foundIDs`
NSArray *linkedPeople = CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(contactPerson));
if (linkedPeople) {
for (id record in linkedPeople) {
[foundIDs addObject:#(ABRecordGetRecordID((__bridge ABRecordRef)record))];
}
} else {
[foundIDs addObject:#(recordId)];
}
}
}
CFRelease(addressBook);
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"fullName" ascending:YES];
[self.tableData sortUsingDescriptors:#[descriptor]];
Having said that, you probably should iterate through all of the linked contacts and look for phone numbers there, too. Maybe do some validation of the names, too (e.g. if you have one entry for J. D. Salinger and another for John David Salinger, have some algorithm for figuring out which name you want to use). There's a lot you could do. But the above illustrates a minimalistic solution which adds the contact and any linked contacts to the list of contacts already found.

Access exchange contacts on device

I have an app, that needs to get the user's contacts
providing the user gave access to the contacts
How do i get the exchange contacts ?
I tried the normal method of accessing the phone book, but i want to create my own ui
and in my own ui, only the local contacts appear
this is my code to get the contacts
- (void)reloadAddressBook
{
// Create addressbook data model
NSMutableArray *contactsTemp = [NSMutableArray array];
ABAddressBookRef addressBooks = [(TKPeoplePickerController*)self.navigationController addressBook];
CFArrayRef allPeople;
CFIndex peopleCount;
if (_group) {
self.title = _group.name;
ABRecordRef groupRecord = ABAddressBookGetGroupWithRecordID(addressBooks, (ABRecordID)_group.recordID);
allPeople = ABGroupCopyArrayOfAllMembers(groupRecord);
peopleCount = (CFIndex)_group.membersCount;
} else {
self.title = NSLocalizedString(#"All Contacts", nil);
allPeople = ABAddressBookCopyArrayOfAllPeople(addressBooks);
peopleCount = ABAddressBookGetPersonCount(addressBooks);
}
for (NSInteger i = 0; i < peopleCount; i++)
{
ABRecordRef contactRecord = CFArrayGetValueAtIndex(allPeople, i);
if (!contactRecord) continue;
CFStringRef abName = ABRecordCopyValue(contactRecord, kABPersonFirstNameProperty);
CFStringRef abLastName = ABRecordCopyValue(contactRecord, kABPersonLastNameProperty);
CFStringRef abFullName = ABRecordCopyCompositeName(contactRecord);
Contact *contact = [[Contact alloc] init];
NSString *fullNameString;
NSString *firstString = (__bridge NSString *)abName;
NSString *lastNameString = (__bridge NSString *)abLastName;
if ((__bridge id)abFullName != nil) {
fullNameString = (__bridge NSString *)abFullName;
} else {
if ((__bridge id)abLastName != nil)
{
fullNameString = [NSString stringWithFormat:#"%# %#", firstString, lastNameString];
}
}
if([fullNameString isEqualToString:#"אלי"]){
LogInfo(#"found eli");
}
contact.name = fullNameString;
contact.recordID = (int)ABRecordGetRecordID(contactRecord);
contact.rowSelected = NO;
contact.lastName = (__bridge NSString*)abLastName;
contact.firstName = (__bridge NSString*)abName;
ABPropertyID multiProperties[] = {
kABPersonPhoneProperty,
kABPersonEmailProperty
};
NSInteger multiPropertiesTotal = sizeof(multiProperties) / sizeof(ABPropertyID);
for (NSInteger j = 0; j < multiPropertiesTotal; j++) {
ABPropertyID property = multiProperties[j];
ABMultiValueRef valuesRef = ABRecordCopyValue(contactRecord, property);
NSInteger valuesCount = 0;
if (valuesRef != nil) valuesCount = ABMultiValueGetCount(valuesRef);
if (valuesCount == 0) {
CFRelease(valuesRef);
continue;
}
for (NSInteger k = 0; k < valuesCount; k++) {
CFStringRef value = ABMultiValueCopyValueAtIndex(valuesRef, k);
switch (j) {
case 0: {// Phone number
contact.tel = [(__bridge NSString*)value telephoneWithReformat];
break;
}
case 1: {// Email
contact.email = (__bridge NSString*)value;
break;
}
}
CFRelease(value);
}
CFRelease(valuesRef);
if(contact.tel.length == 0){
continue;
}
}
[contactsTemp addObject:contact];
if (abName) CFRelease(abName);
if (abLastName) CFRelease(abLastName);
if (abFullName) CFRelease(abFullName);
}
if (allPeople) CFRelease(allPeople);
// Sort data
UILocalizedIndexedCollation *theCollation = [UILocalizedIndexedCollation currentCollation];
SEL sorter = ABPersonGetSortOrdering() == kABPersonSortByFirstName ? NSSelectorFromString(#"sorterFirstName") : NSSelectorFromString(#"sorterLastName");
for (TKContact *contact in contactsTemp) {
NSInteger sect = [theCollation sectionForObject:contact
collationStringSelector:sorter];
contact.sectionNumber = sect;
}
NSInteger highSection = [[theCollation sectionTitles] count];
NSMutableArray *sectionArrays = [NSMutableArray arrayWithCapacity:highSection];
for (int i=0; i<=highSection; i++) {
NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:1];
[sectionArrays addObject:sectionArray];
}
for (TKContact *contact in contactsTemp) {
[(NSMutableArray *)[sectionArrays objectAtIndex:contact.sectionNumber] addObject:contact];
}
for (NSMutableArray *sectionArray in sectionArrays) {
NSArray *sortedSection = [theCollation sortedArrayFromArray:sectionArray collationStringSelector:sorter];
[_listContent addObject:sortedSection];
}
[self.tableView reloadData];
}

I am retrieving contact's multiple addresses but only want Home address

Does anyone know how to retrieve the Home address from multiaddress in iOS? I have got permission from user and everything else but the problem is, I only want the Home address.
ABAddressBookRef addressBook = ABAddressBookCreate();
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
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);
dispatch_release(sema);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *array = [[NSMutableArray alloc] init];
for( int i = 0 ; i < nPeople ; i++ )
{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i );
// First Name
NSString *fName = (__bridge NSString*)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
// Last Name
NSString *lName = (__bridge NSString*)ABRecordCopyValue(ref, kABPersonLastNameProperty);
// Phone
ABMultiValueRef phoneMultiValue = ABRecordCopyValue(ref, kABPersonPhoneProperty);
CFArrayRef allPhones = ABMultiValueCopyArrayOfAllValues(phoneMultiValue);
NSMutableArray *phoneData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allPhones];
// Email
ABMultiValueRef emailMultiValue = ABRecordCopyValue(ref, kABPersonEmailProperty);
CFArrayRef allEmails = ABMultiValueCopyArrayOfAllValues(emailMultiValue);
NSMutableArray *emailData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allEmails];
// Address
ABMultiValueRef addressMultiValue = ABRecordCopyValue(ref, kABPersonAddressProperty);
CFArrayRef allAddresses = ABMultiValueCopyArrayOfAllValues(addressMultiValue);
NSMutableArray* addressData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allAddresses];
for ( int j = 0 ; j < [addressData count]; j++) {
if ([[addressData objectAtIndex:j] count] > 0) {
if ([fName length] > 0 || [lName length] > 0) {
if ([fName length] > 0) {
[dic setObject:fName forKey:#"FirstName"];
}
if ([lName length] > 0) {
[dic setObject:lName forKey:#"LastName"];
}
if ([phoneData count] > 0) {
[dic setObject:phoneData forKey:#"MultiplePhoneNumbers"];
}
if ([emailData count] > 0) {
[dic setObject:emailData forKey:#"MultipleEmails"];
}
[dic setObject:addressData forKey:#"MultipleAddresses"];
}
}
}
NSUInteger keyCount = [[dic allKeys] count];
if (keyCount > 0) {
ABRecordID recId = ABRecordGetRecordID(ref);
[dic setObject:[NSString stringWithFormat:#"%d",recId] forKey:#"ABRecordRef"];
[dic setObject:[NSString stringWithFormat:#"%d",i] forKey:#"ab_id"];
[dic setObject:[NSNumber numberWithBool:FALSE] forKey:#"is_coordinate_fetch"];
[array addObject:dic];
}
I would really appreciate if anyone could take time and solve this for me.
You need to iterate through the kABPersonAddressProperty multivalue property and extract the one matching the kABHomeLabel identifier. Here is how you could do it in iOS 7 (assumes a reference to the address book):
NSArray *people = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(localAddressBook));
// Iterate through each person in the Address Book
for (NSUInteger i = 0; i < people.count; i++)
{
ABRecordRef person = CFArrayGetValueAtIndex((__bridge CFArrayRef)people, i);
// Access the person's addresses (a ABMultiValueRef)
ABMultiValueRef addressesProperty = CFAutorelease(ABRecordCopyValue(person, kABPersonAddressProperty));
if (addressesProperty)
{
// Iterate through the address multivalue
for (CFIndex index = 0; index < ABMultiValueGetCount(addressesProperty); index++)
{
// Get the address label
NSString *addressLabel = (NSString *)CFBridgingRelease(ABMultiValueCopyLabelAtIndex(addressesProperty, index));
// Check for home address label
if ([addressLabel isEqualToString:(NSString *)kABHomeLabel])
{
// Your code here
NSLog(#"%#", addressLabel);
}
}
}
}
There is no single solution to this problem. What I did in my app to do this was as follows:
1) If the person just had one address, use that.
2) If there was more than one address, using cells that had the name and the first address, and a button that said "Select different Address". If the user taps that button, animate up a sheet where the user sees another table of all addresses, and can choose the one they want.

iOS open specific contact info

i know how to call the contact view but if someone could tell me how to call a specific contact .
To call the view i am calling this method
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentModalViewController:picker animated:YES];
and i am getting the info and storing in into plist
+ (NSInteger) exportContacts
{
ABAddressBookRef addressBook = ABAddressBookCreate();
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
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);
dispatch_release(sema);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
NSMutableArray *array = [[NSMutableArray alloc] init];
if (accessGranted) {
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for( int i = 0 ; i < nPeople ; i++ )
{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i );
// First Name
NSString *fName = (__bridge NSString*)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
// Record Id
int recid = ABRecordGetRecordID(ref);
NSLog(#"Record Id %d",recid);
// Last Name
NSString *lName = (__bridge NSString*)ABRecordCopyValue(ref, kABPersonLastNameProperty);
// Phone
ABMultiValueRef phoneMultiValue = ABRecordCopyValue(ref, kABPersonPhoneProperty);
CFArrayRef allPhones = ABMultiValueCopyArrayOfAllValues(phoneMultiValue);
NSMutableArray *phoneData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allPhones];
// Email
ABMultiValueRef emailMultiValue = ABRecordCopyValue(ref, kABPersonEmailProperty);
CFArrayRef allEmails = ABMultiValueCopyArrayOfAllValues(emailMultiValue);
NSMutableArray *emailData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allEmails];
// Address
ABMultiValueRef addressMultiValue = ABRecordCopyValue(ref, kABPersonAddressProperty);
CFArrayRef allAddresses = ABMultiValueCopyArrayOfAllValues(addressMultiValue);
NSMutableArray* addressData = [NSMutableArray arrayWithArray:(__bridge NSArray*) allAddresses];
for ( int j = 0 ; j < [addressData count]; j++) {
if ([[addressData objectAtIndex:j] count] > 0) {
if ([fName length] > 0 || [lName length] > 0) {
if ([fName length] > 0) {
[dic setObject:fName forKey:#"FirstName"];
}
if ([lName length] > 0) {
[dic setObject:lName forKey:#"LastName"];
}
if ([phoneData count] > 0) {
[dic setObject:phoneData forKey:#"MultiplePhoneNumbers"];
}
if ([emailData count] > 0) {
[dic setObject:emailData forKey:#"MultipleEmails"];
}
[dic setObject:addressData forKey:#"MultipleAddresses"];
// store the ref id here
NSLog(#"%#",addressData);
}
}
}
NSUInteger keyCount = [[dic allKeys] count];
if (keyCount > 0) {
[dic setObject:[NSString stringWithFormat:#"%d",i] forKey:#"ab_id"];
[dic setObject:[NSNumber numberWithBool:FALSE] forKey:#"is_coordinate_fetch"];
[array addObject:dic];
}
}
[ApplicationUtility setPlistDataWithKey:KEY_ADDRESS_BOOK WithObject:array];
}
return [array count];
}
Take a look at the ABPersonViewController class reference.

ABAddressBookRef leaking in iOS

I'm parsing the address book in iOS but the Leaks instrument is reporting big memory leaks, I can't seem to track the problem down
First I create the address book.
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
This is what I suspect is leaking, but ABAddressBookRef and CFArrayRef get autoreleased right?
The rest of my code is below..
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *List = [[NSMutableArray alloc] init];
for (int i = 0; i < nPeople; i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
NSNumber *recordId = [NSNumber numberWithInteger:ABRecordGetRecordID(ref)];
CFStringRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
CFDataRef imgData = ABPersonCopyImageData(ref);
ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType);
multi = ABRecordCopyValue(ref,kABPersonEmailProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
CFStringRef email, emailLabel;
emailLabel = ABMultiValueCopyLabelAtIndex(multi, i);
email = ABMultiValueCopyValueAtIndex(multi, i);
NSString *emails = [NSString stringWithFormat: #"%#", (NSString *)email];
if (emails)
{
NSMutableDictionary *addDict = [[NSMutableDictionary alloc] init];
[addDict addObject:emails forKey:#"email"];
[List addObject:addDict];
[addDict release];
}
CFRelease(email);
CFRelease(emailLabel);
}
if (firstName) {
CFRelease(firstName);
}
if (lastName) {
CFRelease(lastName);
}
if (imgData) {
CFRelease(imgData);
}
if (ref) {
CFRelease(ref);
}
CFRelease(multi);
}
//do something with list
[List release];
Ok this works and doesn't leak
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *List = [[NSMutableArray alloc] init];
for (int x = 0; x < nPeople; x++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, x);
ABMultiValueRef emailMultiValue = ABRecordCopyValue(ref, kABPersonEmailProperty);
NSArray *emailAddresses = [(NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue) autorelease];
for (int i = 0; i < [emailAddresses count]; i++) {
NSString *emails = [emailAddresses objectAtIndex:i];
if (emails)
{
NSMutableDictionary *addDict = [[NSMutableDictionary alloc] init];
[addDict addObject:emails forKey:#"email"];
[List addObject:addDict];
[addDict release];
}
}
if (emailMultiValue)
{
CFRelease(emailMultiValue);
}
if (ref) {
CFRelease(ref);
}
}
//do something with list
[List release];
CFRelease(allPeople);
Actually to eliminate all leaks you also need to be releasing the ABAddressBookRef - just follow Core Foundation naming guidelines - you got the reference using "ABAddressBookCreate()" and any function with Create or Copy needs to be released.
CFErrorRef error = NULL;
ABAddressBookRef addressbk=ABAddressBookCreateWithOptions(NULL, &error);
if (addressbk != nil)
{
NSLog(#"Succesful.");
NSArray *allContacts=(NSArray *)ABAddressBookCopyArrayOfAllPeople(addressbk); //type casting nsarray from CFArrayRef
NSUInteger i = 0;
for (i = 0; i < [allContacts count]; i++)
{
Category *mCategory = [[Category alloc]init];
ABRecordRef contactPerson = ( ABRecordRef)allContacts[i];
NSString *firstName = ( NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = ( NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSString *fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
mCategory.firstName = firstName;
mCategory.lastName = lastName;
mCategory.fullName = fullName;
//email
ABMultiValueRef emails = ABRecordCopyValue(contactPerson, kABPersonEmailProperty);
NSUInteger j = 0;
for (j = 0; j < ABMultiValueGetCount(emails); j++)
{
NSString *email = ( NSString *)ABMultiValueCopyValueAtIndex(emails, j);
if (j == 0)
{
mCategory.homeEmail = email;
NSLog(#"mCategory.homeEmail = %# ", mCategory.homeEmail);
}
else if (j==1)
mCategory.workEmail = email;
}
[self.arrAddress addObject:mCategory];
[mCategory release];
mCategory=nil;
}
}
CFRelease(addressbk);

Resources