1

I am trying to interact with ABAddressBook, but when analysing the code in Xcode I have some memory leak warnings that I cannot resolve. I get the warnings "Potential leak of an object" and "Potential leak of an object stored into 'allContacts'"

+ (void)addNewContact:(BusinessCard *)contact {
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil);
ABRecordRef newContact = ABPersonCreate();
if (contact.firstName) ABRecordSetValue(newContact, kABPersonFirstNameProperty, (__bridge CFStringRef)contact.firstName, nil);
if (contact.familyName) ABRecordSetValue(newContact, kABPersonLastNameProperty, (__bridge CFStringRef)contact.familyName, nil);
if (contact.company) ABRecordSetValue(newContact, kABPersonOrganizationProperty, (__bridge CFStringRef)contact.company, nil);
if (contact.jobTitle) ABRecordSetValue(newContact, kABPersonJobTitleProperty, (__bridge CFStringRef)contact.jobTitle, nil);
if (contact.emailAddress) {
    ABMutableMultiValueRef multiEmail = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    ABMultiValueAddValueAndLabel(multiEmail, (__bridge CFTypeRef)(contact.emailAddress), kABWorkLabel, NULL);
    ABRecordSetValue(newContact, kABPersonEmailProperty, multiEmail, NULL);
    CFRelease(multiEmail);
}

if (contact.details) ABRecordSetValue(newContact, kABPersonNoteProperty, (__bridge CFStringRef)contact.details, nil);


if (contact.phone) {
    ABMutableMultiValueRef phoneNumbers = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    ABMultiValueAddValueAndLabel(phoneNumbers, (__bridge CFStringRef)contact.phone, kABPersonPhoneMainLabel, NULL);
    ABRecordSetValue(newContact, kABPersonPhoneProperty, phoneNumbers, nil);
    CFRelease(phoneNumbers);
}

ABAddressBookAddRecord(addressBookRef, newContact, nil);
CFRelease(newContact);

NSArray *allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBookRef);
for (id record in allContacts){
    ABRecordRef thisContact = (__bridge ABRecordRef)record;
    if (CFStringCompare(ABRecordCopyCompositeName(thisContact), ABRecordCopyCompositeName(newContact), 0) == kCFCompareEqualTo){
        [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Existing contact", @"Title for alert view when adding an existing contact") message:NSLocalizedString(@"A contact already exists with the same name. Do you want to add the new contact?", @"Message for alert view when adding an existing contact")
                           cancelButtonItem:[RIButtonItem itemWithLabel:NSLocalizedString(@"No", @"No")]
                           otherButtonItems:[RIButtonItem itemWithLabel:NSLocalizedString(@"Yes", @"Yes")   action:^{
            [self saveInAddressBook:addressBookRef];
        }], nil] show]; //Potential leak of an object

        NSLog(@"Contact exists");
        return;
    }

}

[self saveInAddressBook:addressBookRef]; //Potential leak of an object stored into 'allContacts'
CFRelease(addressBookRef);
NSLog(@"Contact created");
}

+ (void)saveInAddressBook:(ABAddressBookRef)addressBookRef {
    ABAddressBookSave(addressBookRef, nil);
    [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Contact added", @"Title for alert view when contact is successfully added to address book") message:nil delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"OK") otherButtonTitles:nil] show];
}

Does anyone know how I can fix these issues?

Jorn
  • 1,054
  • 9
  • 25
  • There is a very helpful library available for managing address book: https://github.com/Alterplay/APAddressBook – Aneeq Anwar May 12 '15 at 09:27

2 Answers2

2

You forgot

CFRelease((__bridge CFTypeRef) allContacts);

I think you can put it like this:

for (id record in allContacts){
    ...
}

CFRelease((__bridge CFTypeRef) allContacts);
[self saveInAddressBook:addressBookRef]; //Potential leak of an object stored into 'allContacts'
CFRelease(addressBookRef);
NSLog(@"Contact created");
Massimo Polimeni
  • 4,826
  • 4
  • 27
  • 54
  • Thank you! I did not do the bridging in the CFRelease, which caused it to fail. I both tried CFRelease(allContacts) (that unsurprisingly didn't work), and allContacts = nil. You saved my day :-) – Jorn May 12 '15 at 10:57
  • 1
    eheh I'm happy to have helped you :) – Massimo Polimeni May 12 '15 at 11:58
0

You could either go ahead and use APAddressBook which is a extremely well built framework for Addressbook.

OR the flow that usually helped me fix my crashes related to Addressbook was by following the optimizations suggested by the XCode

In XCode goto Product -> Analyze.

You must see a couple of issues when it completes.

Vijay Tholpadi
  • 2,135
  • 1
  • 15
  • 20