I am using using this function to access the contacts list and saving the contact object using MContact class,but this code is giving me several memory leaks,i am not able to figure this out .Please help!
+(NSArray *)getAllContacts
{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
__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);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
#ifdef DEBUG
NSLog(@"Fetching contact info ----> ");
#endif
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++)
{
MContact *contacts = [MContact new];
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
//get First Name and Last Name
contacts.firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
contacts.lastName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
if (!contacts.firstName) {
contacts.firstName = @"";
}
if (!contacts.lastName) {
contacts.lastName = @"";
}
NSMutableArray *contactEmails = [NSMutableArray new];
ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
NSString *contactEmail = (__bridge NSString *)contactEmailRef;
[contactEmails addObject:contactEmail];
// NSLog(@"All emails are:%@", contactEmails);
}
if([contactEmails count]==0){
return items ;
}
else{
[contacts setemails:contactEmails];
[items addObject:contacts];
}
#ifdef DEBUG
#endif
}
CFRelease(addressBook);
return items;
} else {
#ifdef DEBUG
NSLog(@"Cannot fetch Contacts :( ");
#endif
return NO;
}
}
The thing you need to watch out for here is that, by convention, functions that "copy" return objects with incremented reference counts, just like functions that "create". So, the way you've CFReleased your
addressBook, you need to do that with the copied objects too. Alternatively, when you bridge your CFObjects to NSObjects, a__bridge_transferwould pass ownership to ARC, so ARC can release it for you.The other gotcha here is the multiple return points in the function. If that's what you want to do, you need to make sure that appropriate things are cleaned up before each
return.Hopefully I've caught everything here: