Memory leak with CFArray in ARC

2019-07-27 04:24发布

问题:

I've made an iPhone app using ARC that accesses every entry in the address book, and then every address for every person. The data is stored in CFArrays, which are toll-free bridged to NSArrays. The code is below.

ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSArray *peopleArray =[(__bridge NSArray *) arrayRef copy];
CFRelease(arrayRef);
arrayRef = nil;

for(id personId in peopleArray)
{
    ABRecordRef person = (__bridge ABRecordRef) personId;
    //process other attributes of the address book

    ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonAddressProperty);
    CFArrayRef addressRef = ABMultiValueCopyArrayOfAllValues(multi);
    NSArray *addressArray = [(__bridge NSArray *) addressRef copy];

    for(NSDictionary *address in addressArray)
    {
       //process the addresses
    }
    CFRelease(addressRef);
    addressRef = nil;
}

From what I've researched on the internet and in Apple's Memory Management guides, this looks like the proper way to do it. The problem is when I got to run the code, it halts on "CFRelease(addressRef)", highlighted green with text "Thread 1" (not sure what this error means). I've also tried putting the CFRelease before the for loop, but the same issue occurs.

If I remove the CFRelease, it compiles, but there is a memory leak at the creation of addressArray. Does anyone know how to solve this problem? I can't seem to figure it out using ARC.

回答1:

Instead of NSArray *peopleArray =[(__bridge NSArray *) arrayRef copy]; CFRelease(arrayRef);, use NSArray *peopleArray = CFBridgingRelease(arrayRef). This transfers ownership of the object to ARC.



回答2:

Whenever you see "Copy" in a method name you should use (__bridge_transfer <ObjectType> *)

Then ARC will be responsible for releasing the object.

So your code will look like:

NSArray *peopleArray = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);