Access exchange contacts on device - ios

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];
}

Related

In a try to fix NSRangeException error

I've caught an error:
Fatal Exception: NSRangeException
*** -[__NSArrayI objectAtIndex:]: index 1330 beyond bounds [0 .. 1329]
At string
NSArray *currentABRecords = [ApplicationPhoneDirectory records];
ApplicationPhoneDirectory is NSObject with unique contacts (dict and array).
But I think the error is about working with memory, how can I manage it more properly to avoid appearance of such a problem?
Or, in case if I'm incorrect I can put records part in there.
upd:
static NSArray *RecordsForABInterval(UInt32 start, UInt32 end, CFArrayRef allPeople) {
NSMutableArray *peoples = [NSMutableArray arrayWithCapacity:(end - start) * 2];
for (int i = (int) start; i < end; i++) {
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
NSString *firstName = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSString *fullName = [NSString stringWithFormat:#"%# %#",
firstName.length > 0 ? firstName : #"",
lastName.length > 0 ? lastName : #""];
fullName = [fullName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
ABMutableMultiValueRef phoneList = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phonesCount = ABMultiValueGetCount(phoneList);
for (int j = 0; j < phonesCount; ++j) {
CFTypeRef ABphone = ABMultiValueCopyValueAtIndex(phoneList, j);
NSString *phone = (NSString *)CFBridgingRelease(ABphone);
NSString *phoneInSMFormat = [phone phoneNumberInSMFormat];
if ([phoneInSMFormat isValidSMPhoneNumber]) {
NSDictionary *record = #{
#"name" : fullName,
#"phone" : phoneInSMFormat,
#"original" : phone
};
[peoples addObject:record];
}
}
if (phoneList != NULL) {
CFRelease(phoneList);
}
}
return peoples;
}
+ (NSArray *)records {
const int MaxAutoreleaseStep = 500;
NSMutableArray *records = [NSMutableArray array];
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
__block BOOL accessGranted = NO;
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_async(dispatch_get_main_queue(), ^{
accessGranted = granted;
});
});
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
accessGranted = YES;
}
else {
// The user has previously denied access
// Send an alert telling user to change privacy setting in settings app
if (addressBook != NULL) {
CFRelease(addressBook);
}
return nil;
}
// TODO: review this logic - should it be a single call to AB?
if (addressBook != NULL) {
CFRelease(addressBook);
}
if (accessGranted) {
ABAddressBookRef addressbook = ABAddressBookCreateWithOptions(NULL, &error);
if (error != NULL) {
if (addressbook != NULL) {
CFRelease(addressbook);
}
return nil;
}
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressbook);
CFIndex peopleCount = ABAddressBookGetPersonCount(addressbook);
for (int start = 0; start < peopleCount; start += MaxAutoreleaseStep) {
#autoreleasepool {
int end = start + MaxAutoreleaseStep;
NSArray *contactListCut = RecordsForABInterval((UInt32) start, (UInt32) MIN((int)peopleCount, end), allPeople);
[records addObjectsFromArray:contactListCut];
}
}
if (allPeople != NULL) {
CFRelease(allPeople);
}
if (addressbook != NULL) {
CFRelease(addressbook);
}
}
return records;
}
upd2:
- (NSString *)phoneNumberInSMFormat {
NSString *phone = [self numericPresentation];
if (phone.length > 0 && [phone characterAtIndex:0] == '8') {
NSMutableString *modifiedString = [phone mutableCopy];
[modifiedString replaceCharactersInRange:NSMakeRange(0, 1) withString:#"7"];
phone = modifiedString;
}
return phone;
}
- (BOOL)isValidSMPhoneNumber {
static NSCharacterSet *characterSet = nil;
if (characterSet == nil) {
characterSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
}
if ([self rangeOfCharacterFromSet:characterSet].location != NSNotFound) {
return NO;
}
if (self.length < 7 || self.length > 12) {
return NO;
}
return [self characterAtIndex:0] != '8';
}

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

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);

Is it possible to check a contact whether it is exits in contact list of iPhone or not?

I am developing an app in which i have to save contact in address book, but if the the contact is already saved in contact then it should not save.
But i have no idea is it possible to check a contact whether it is exits in contact list of iPhone or not?
Any help would be appreciated.
Thanks in advance.
Solved issue
-(void)CheckContactIsExits{
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
NSArray *allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
ABRecordRef pet = ABPersonCreate();
ABRecordSetValue(pet, kABPersonFirstNameProperty, (__bridge CFStringRef)#"VoxSci Activation", nil);
for (id record in allContacts){
ABRecordRef thisContact = (__bridge ABRecordRef)record;
if (CFStringCompare(ABRecordCopyCompositeName(thisContact),
ABRecordCopyCompositeName(pet), 0) == kCFCompareEqualTo){
NSLog(#"The contact already exists");
//The contact already exists!
isContactExits=YES;
}
}
}
Assuming your using Apples framework for this your user will be given the option to "create new contact" or if its already in the contacts list "add to existing contact". Therefore the user can decide if it should be added or not
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
And read all the contacts in iPhone and check the name or phone exit or not.
Check Contact is Exit or Not By Contact Number
Note : Only replace checkingPhoneNumber variable by your checking contact number
ABAddressBookRef * addressbook = ABAddressBookCreateWithOptions(Nil, Nil);
NSArray *people = (__bridge NSArray*)ABAddressBookCopyArrayOfAllPeople(addressbook);
NSMutableArray *phoneArray=[[NSMutableArray alloc] init];
for(id person in people)
{
// get person contact number
ABMultiValueRef phones = (ABMultiValueRef)ABRecordCopyValue((__bridge ABRecordRef)(person), kABPersonPhoneProperty);
NSString* mobile=#"";
NSString* mobileLabel;
for (int i=0; i < ABMultiValueGetCount(phones); i++)
{
mobileLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel]) {
NSLog(#"mobile:");
} else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel]) {
NSLog(#"iphone:");
} else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhonePagerLabel]) {
NSLog(#"pager:");
}
mobile = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(#"%#", mobile);
// remove all spaces bracket from contact number
NSMutableString *newPhoneStr = [[NSMutableString alloc] init];;
int j = [mobile length];
for (int i=0; i<j; i++)
{
if ([mobile characterAtIndex:i] >=48 && [mobile characterAtIndex:i] <=59)
{
[newPhoneStr appendFormat:#"%c",[mobile characterAtIndex:i]];
}
}
//add contact into phoneArray
[phoneArray addObject:newPhoneStr];
}
}
NSLog(#"%#",phoneArray);
BOOL identicalStringFound = NO;
// remove all spaces bracket from contact number which is check
NSMutableString *newCheckingPhoneNumberStr = [[NSMutableString alloc] init];
int j = [checkingPhoneNumber length];
for (int i=0; i<j; i++)
{
if ([checkingPhoneNumber characterAtIndex:i] >=48 && [[profileDetailsDict valueForKey:#"mobile"] characterAtIndex:i] <=59)
{
[newCheckingPhoneNumberStr appendFormat:#"%c",[checkingPhoneNumber characterAtIndex:i]];
}
}
for (NSString *contact in phoneArray)
{
if ([contact isEqual:newCheckingPhoneNumberStr])
{
identicalStringFound = YES;
break;
}
}
if(identicalStringFound)
{
// checkingPhoneNumber is exit
}
else
{
// checkingPhoneNumber is not exit
}
If anybody wants to check name is saved in address book or not, then below function may be useful:
-(BOOL)isNameSaved:(NSString*)strGivenName {
BOOL isSaved = NO;
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for ( int i = 0; i < nPeople; i++ ) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
CFStringRef firstc = (CFStringRef)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
NSString *first = [NSString stringWithFormat:#"%#",firstc];
if ([first isEqualToString:strGivenName]) {
isSaved = YES;
break;
}
}
return isSaved;
}

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.

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