I'm trying to work with the adress book, but my understanding of memory management is so-so at best.
My project is using Automatic Reference Counting (ARC), but as I've learned, ARC only manages retain/release in Objective-C land.
I understand that my first function call: ABAddressBookCreate() returns an ABAddressBookRef that I "own", because I'm getting it from a method with Create in the name. I CFRelease it when I'm done with it.
What I don't understand is how the ABRecordRef stays alive during the course of this method. Shouldn't I have to CFRetain and CFRelease it? I have another nearly identical method in the same class that was crashing if I didn't retain/release the ABAddressBookRef.
ABAddressBookRef iPhoneAddressBook = ABAddressBookCreate();
ABRecordRef record = ABAddressBookGetPersonWithRecordID(iPhoneAddressBook, self.addressBookRecordID);
NSString *firstName = (__bridge_transfer NSString*)ABRecordCopyValue(record, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString*)ABRecordCopyValue(record, kABPersonLastNameProperty);
NSString *fullName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
ABMultiValueRef phoneRef = ABRecordCopyValue(record, kABPersonPhoneProperty);
// Set up an NSArray and copy the values in.
NSArray *phoneNumberArray = (__bridge_transfer id)ABMultiValueCopyArrayOfAllValues(phoneRef);
CFRelease(iPhoneAddressBook);
// Finally, do stuff with contact information in Obj-C land..
Exit question: have I created a leak by not calling CFRelease with my ABMultiValueRef phoneRef on the last line?
When dealing with Core Foundation memory management, you want to refer to these ownership policies.
The key to your question lies in the "Get Rule", which states that any CF* object you get from and Core Foundation function that contains the word "Get", you don't own it and can't guarantee it's lifespan. The important distinction is between "can't guarantee validity" and "isn't valid". It's possible for you to have a reference to an object that you don't own, but whose lifespan is being supported by some other source. In that case, you'll still be able to use it without crashing.
That's technically what's happening with your ABRecordRef. You haven't taken ownership of it, but it's extremely likely that the ABAddressBookRef that you're getting the record from does own it, and is therefore keeping it alive. As long as that ABAddressBookRef is valid, its records will also be valid. If you were to call CFRelease(iPhoneAddressBook); and then attempt to use the record, I'm betting it would explode.
Finally, for your exit question - Yes, you're leaking the ABMultiValueRef per the "Create" rule, which states that you own objects received via functions containing "Create" or "Copy".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With