ABAddressBookRef leaking in iOS - 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);

Related

when it's running here : CFRelease(book); that EXC_BAD_ACCESS (code=EXC_l386_GPFLT)

CFRelease(book); the variable of book is an object of ABAddressBookRef.
Why I got this crashed?
The entirely code below:
- (NSArray *)getAllContactsBeneathiOS9:(NSString *__autoreleasing *)err
{
__block NSMutableArray *contactArray = [[NSMutableArray alloc] init];
//1.Create Address Book instance.
ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL);
//2.Request to access the Address Book
ABAddressBookRequestAccessWithCompletion(book, ^(bool granted, CFErrorRef error) {
if(granted){
//Access Success
NSArray * allPeople = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(book);
for (int i = 0; i < allPeople.count; i++) {
ABRecordRef alPeople = (__bridge ABRecordRef)(allPeople[i]);
ZRContactItem *item = [[ZRContactItem alloc] init];
NSString *firstName = (__bridge NSString *)ABRecordCopyValue(alPeople, kABPersonFirstNameProperty);
NSString *middleName = (__bridge NSString *)ABRecordCopyValue(alPeople, kABPersonMiddleNameProperty);
NSString *lastName = (__bridge NSString *)ABRecordCopyValue(alPeople, kABPersonLastNameProperty);
ABMultiValueRef phone = ABRecordCopyValue(alPeople, kABPersonPhoneProperty);
CFArrayRef phoneArray = ABMultiValueCopyArrayOfAllValues(phone);
NSMutableArray *phoneList = [[NSMutableArray alloc] init];
if (phoneArray) {
CFIndex phoneCount = CFArrayGetCount(phoneArray);
for (CFIndex j = 0 ; j < phoneCount; j++) {
CFStringRef mobile = ABMultiValueCopyValueAtIndex(phone, j);
[phoneList addObject:(__bridge NSString *)mobile];
CFRelease(mobile);
}
}
if (phoneArray) CFRelease(phoneArray);
if (phone) CFRelease(phone);
ABMultiValueRef email = ABRecordCopyValue(alPeople, kABPersonEmailProperty);
CFArrayRef emailArray = ABMultiValueCopyArrayOfAllValues(email);
NSMutableArray *emailList = [[NSMutableArray alloc] init];
if (emailArray) {
CFIndex emailCount = CFArrayGetCount(emailArray);
for (CFIndex j = 0 ; j < emailCount; j++) {
CFStringRef mail = ABMultiValueCopyValueAtIndex(email, j);
[emailList addObject:(__bridge NSString *)mail];
CFRelease(mail);
}
}
if (emailArray) CFRelease(emailArray);
if (email) CFRelease(email);
ABMultiValueRef address = ABRecordCopyValue(alPeople, kABPersonAddressProperty);
CFArrayRef addrArray = ABMultiValueCopyArrayOfAllValues(address);
NSMutableArray *addrList = [[NSMutableArray alloc] init];
if (addrArray) {
CFDictionaryRef dic = CFArrayGetValueAtIndex(addrArray, 0);
NSString *city = (__bridge NSString *)CFDictionaryGetValue(dic, kABPersonAddressCityKey);
NSString *CountryCode = (__bridge NSString *)CFDictionaryGetValue(dic, kABPersonAddressCountryCodeKey);
NSString *Country = (__bridge NSString *)CFDictionaryGetValue(dic, kABPersonAddressCountryKey);
NSString *State = (__bridge NSString *)CFDictionaryGetValue(dic, kABPersonAddressStateKey);
NSString *Street = (__bridge NSString *)CFDictionaryGetValue(dic, kABPersonAddressStreetKey);
NSString *ZIP = (__bridge NSString *)CFDictionaryGetValue(dic, kABPersonAddressZIPKey);
NSMutableDictionary *dic1 = [[NSMutableDictionary alloc] init];
dic1[#"street"] = Street;
dic1[#"city"] = city;
dic1[#"state"] = State;
dic1[#"postalCode"] = ZIP;
dic1[#"country"] = Country;
dic1[#"countryCode"] = CountryCode;
[addrList addObject:dic1];
CFRelease(dic);
}
if (addrArray) CFRelease(addrArray);
if (address) CFRelease(address);
item.givenName = [self isnil:firstName];
item.familyName = [self isnil:lastName];
item.middleName = [self isnil:middleName];
item.phoneNumbers = phoneList;
item.email = emailList;
item.address = addrList;
[contactArray addObject:item];
if (alPeople) CFRelease(alPeople);
}
}else{
//Access denied.
*err = #"Grant this application to access your Contacts, please! ";
NSLog(#"%#", *err);
}
//Release book instance
if (book) CFRelease(book);
});
return contactArray;
}
When it is running CFRelease(book); that is crashed. Why?
I have already determined the variable of book is not nil, so that it can release.
Any help is appreciated!
First of all, ABAddressBookRequestAccessWithCompletion is an asynchronous function. It returns immediately, and the block you pass to it is executed at some later point. The contact array you return will always be empty.
As for the crash, if you call CFRelease at all, it shouldn't be inside the block. You don't know what ABAddressBookRequestAccessWithCompletion does with the book reference after running the block!
Try doing a bridge transfer to an ARC managed property and just hold on to it while you work with the address book.

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.

how to save one name string and two different length array of email and phone no

As i guess this is a very simple and basic question.
i am using #import <AddressBook/AddressBook.h> to get the contact info of device and i had successfully implemented the same.
Everythings work fine when i got one phone no and one email from each contact. But when i got multiple phone no's and multiple email then getting crash on my app. I guess i am not using the proper saving method.
So i really want to know how to save one name string and one array of email(different length) and phone no(different length) as group for a contact and same for all other. so that it would not be difficult to reproduce the result later on the detail screen
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
[values1 addObject:[NSString stringWithFormat:#"%# %#",firstName,lastName]]; //values1 array to save name of contact
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++) {
NSString* email = (__bridge NSString*)ABMultiValueCopyValueAtIndex(emails, j);
NSLog(#"Email:%#", email);
[values2 addObject:[NSString stringWithFormat:#"%#",email]];
} //values2 array to save email associated to that contact
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSLog(#"phone:%#", phoneNumber);
[values3 addObject:[NSString stringWithFormat:#"%#",phoneNumber]];
}//values3 array to save different phone no's associated to that contacts
NSDictionary *dict = [[NSDictionary alloc]init];
}
AS now i have three array with details contain details of one contact. Now how can merge these three array values to one so that it would be easy to save and fetch data for multiples or hundreds of contacts
ABAddressBookRef allPeople = ABAddressBookCreate();
CFArrayRef allContacts = ABAddressBookCopyArrayOfAllPeople(allPeople);
CFIndex numberOfContacts = ABAddressBookGetPersonCount(allPeople);
NSLog(#"numberOfContacts------------------------------------%ld",numberOfContacts);
for(int i = 0; i < numberOfContacts; i++){
NSString* name = #"";
NSString* phone = #"";
NSString* email = #"";
ABRecordRef aPerson = CFArrayGetValueAtIndex(allContacts, i);
ABMultiValueRef fnameProperty = ABRecordCopyValue(aPerson, kABPersonFirstNameProperty);
ABMultiValueRef lnameProperty = ABRecordCopyValue(aPerson, kABPersonLastNameProperty);
ABMultiValueRef phoneProperty = ABRecordCopyValue(aPerson, kABPersonPhoneProperty);\
ABMultiValueRef emailProperty = ABRecordCopyValue(aPerson, kABPersonEmailProperty);
NSArray *emailArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailProperty);
NSArray *phoneArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(phoneProperty);
if (fnameProperty != nil) {
name = [NSString stringWithFormat:#"%#", fnameProperty];
}
if (lnameProperty != nil) {
name = [name stringByAppendingString:[NSString stringWithFormat:#" %#", lnameProperty]];
}
if ([phoneArray count] > 0) {
if ([phoneArray count] > 1) {
for (int i = 0; i < [phoneArray count]; i++) {
phone = [phone stringByAppendingString:[NSString stringWithFormat:#"%#\n", [phoneArray objectAtIndex:i]]];
}
}else {
phone = [NSString stringWithFormat:#"%#", [phoneArray objectAtIndex:0]];
}
}
if ([emailArray count] > 0) {
if ([emailArray count] > 1) {
for (int i = 0; i < [emailArray count]; i++) {
email = [email stringByAppendingString:[NSString stringWithFormat:#"%#\n", [emailArray objectAtIndex:i]]];
}
}else {
email = [NSString stringWithFormat:#"%#", [emailArray objectAtIndex:0]];
}
}
NSLog(#"NAME : %#",name);
NSLog(#"PHONE: %#",phone);
NSLog(#"EMAIL: %#",email);
NSLog(#"\n");
}
You can see multiple contact and email in log if contact have.

Application crashes while fetching the iPhone's contact list in iOS

I am having the trouble to fetch iPhone contacts.
I have tried to fetch the contact by the following code.
It is working fine in simulator and also worked fine when the contacts are less in the contact list.
In my phone I am having 1000 Contacts. So it crashes on this device. Please guide me if you know the reason.
Here is my code.
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++)
{
NSMutableDictionary *dicContacts = [[NSMutableDictionary alloc]init];
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
[phoneNumbers addObject:phoneNumber];
//NSLog(#"All numbers %#", phoneNumbers);
}
if ([phoneNumbers count] > 0) {
[dicContacts setValue:[phoneNumbers objectAtIndex:0] forKeyPath:#"Contact"];
}
[items addObject:dicContacts];
}
Thanks In Advance
-(void)tkPeoplePickerController:(TKPeoplePickerController*)picker didFinishPickingDataWithInfo:(NSArray*)contacts
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL,error);
[contacts enumerateObjectsUsingBlock:^(id obj,NSUInteger idx, BOOL *stop)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
TKContact *contact = (TKContact*)obj;
NSNumber *personID = [NSNumber numberWithInt:contact.recordID];
ABRecordID abRecordID = (ABRecordID)[personID intValue];
ABRecordRef abPerson = ABAddressBookGetPersonWithRecordID(addressBook, abRecordID);
// Check person image
UIImage *personImage = nil;
if (abPerson != nil && ABPersonHasImageData(abPerson))
{
if ( &ABPersonCopyImageDataWithFormat != nil )
{
// iOS >= 4.1
CFDataRef contactThumbnailData = ABPersonCopyImageDataWithFormat(abPerson, kABPersonImageFormatThumbnail);
personImage = [UIImage imageWithData:(__bridge NSData*)contactThumbnailData];
CFRelease(contactThumbnailData);
ABMultiValueRef emailValues = ABRecordCopyValue(abPerson, kABPersonEmailProperty);
// This is how you extract the first item from the multivalues:
CFStringRef cfEmailAddress = ABMultiValueCopyValueAtIndex(emailValues, 0);
// This is how you convert it to an NSString.
[RSVP_ImageArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
contact.name,#"name",
contact.email,#"email",
[NSString stringWithFormat:#"%d",abRecordID],#"recodeID",
savedImagePath,#"Image",
nil]];
CFDataRef contactImageData = ABPersonCopyImageDataWithFormat(abPerson, kABPersonImageFormatOriginalSize);
CFRelease(contactImageData);
}
else
{
// iOS < 4.1
CFDataRef contactImageData = ABPersonCopyImageData(abPerson);
personImage = [[UIImage imageWithData:(__bridge NSData*)contactImageData] thumbnailImage:CGSizeMake(thumbnailSize, thumbnailSize)];
ABMultiValueRef emailValues = ABRecordCopyValue(abPerson, kABPersonEmailProperty);
// This is how you extract the first item from the multivalues:
CFStringRef cfEmailAddress = ABMultiValueCopyValueAtIndex(emailValues, 0);
// This is how you convert it to an NSString.
[RSVP_ImageArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
contact.name,#"name",
contact.email,#"email",
[NSString stringWithFormat:#"%d",abRecordID],#"recodeID",
savedImagePath,#"Image",
nil]];
CFRelease(contactImageData);
}
}
else
{
ABMultiValueRef emailValues = ABRecordCopyValue(abPerson, kABPersonEmailProperty);
// This is how you extract the first item from the multivalues:
CFStringRef cfEmailAddress = ABMultiValueCopyValueAtIndex(emailValues, 0);
// This is how you convert it to an NSString.
[mutablearray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
contact.name,#"name",
contact.email,#"email",
[NSString stringWithFormat:#"%d",abRecordID],#"recodeID",
savedImagePath,#"Image",
nil]];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
});
[pool drain];
}];
dispatch_async(dispatch_get_main_queue(), ^{
CFRelease(addressBook);
});
});
}
Use this code with it will surely help you.. for reference u can use this link https://github.com/qnibus/TKContactsMultiPicker ... :)
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++)
{
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
[phoneNumbers addObject:[NSString stringWithFormat:#"%#",phoneNumber]];
//NSLog(#"All numbers %#", phoneNumbers);
}
[phoneNumbers retain];

iPhone address book phone numbers

I am doing an iPhone app in Xcode that needs phone book accessing. I need all phone numbers from address book and that should be stored in an NSArray.
//Also you need to include AddressBook.framework
#import <AddressBook/AddressBook.h>
#import <AddressBook/ABAddressBook.h>
#import <AddressBook/ABPerson.h>
[contactList removeAllObjects];
// open the default address book.
ABAddressBookRef m_addressbook = ABAddressBookCreate();
if (!m_addressbook) {
NSLog(#"opening address book");
}
// can be cast to NSArray, toll-free
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(m_addressbook);
CFIndex nPeople = ABAddressBookGetPersonCount(m_addressbook);
// CFStrings can be cast to NSString!
for (int i=0;i < nPeople;i++) {
MContact *contact = [[MContact alloc] init];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
CFStringRef firstName, lastName;
firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
contact.name = [NSString stringWithFormat:#"%# %#", firstName, lastName];
ABMutableMultiValueRef eMail = ABRecordCopyValue(ref, kABPersonEmailProperty);
if(ABMultiValueGetCount(eMail) > 0) {
contact.email = (NSString *)ABMultiValueCopyValueAtIndex(eMail, 0);
[contactList addObject:contact];
}
CFRelease(ref);
CFRelease(firstName);
CFRelease(lastName);
}
Try this,
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
ABMultiValueRef multiPhones = ABRecordCopyValue(person,kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);++i) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (NSString *) phoneNumberRef;
[phoneNumbers addObject:phoneNumber];
}
This code for Xcode 4.5.1>=0, if if you have below version then no need write if condition. just assign ABAddressBookCreate() to addressbook.
__block BOOL accessGranted = NO;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0")) {
NSLog(#"Device version is greater than 6.0");
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
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);
}
}
else{
addressBook = ABAddressBookCreate();
accessGranted = YES;
}
if (accessGranted) {
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(people); i++) {
ABRecordRef person = CFArrayGetValueAtIndex(people, i);
NSString *name = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
ABMultiValueRef multiPhones = ABRecordCopyValue(person,kABPersonPhoneProperty);
NSMutableArray *individualPhoneNumbers = [[NSMutableArray alloc] init];
if (ABMultiValueGetCount(multiPhones) >0) {
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);++i) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
[individualPhoneNumbers addObject:phoneNumber];
}
[phoneNumbers addObject:individualPhoneNumbers];
}
}

Resources