What's the correct way of releasing an object when it also needs to be returned

点点圈 提交于 2019-12-25 05:11:53

问题


I did Analyze and got potential leak of an object stored into warning in my code below

+ (ABAddressBookRef)getABAddressBookRef {
    unsigned long long lastAddressBookGeneration = _addressBookGeneration;
    unsigned long long addressBookGeneration =[[NSThread currentThread].threadDictionary[kAddressBookGeneration] unsignedLongLongValue];
    ABAddressBookRef addressBook = (__bridge ABAddressBookRef)[NSThread currentThread].threadDictionary[kAddressBook];

    if (addressBook == nil || (addressBookGeneration != lastAddressBookGeneration)) {
        if (addressBook) {
            if ([NSThread isMainThread]) {
                ABAddressBookUnregisterExternalChangeCallback(addressBook,_ExternalChangeCallback, nil);
            }
            [[NSThread currentThread].threadDictionary removeObjectForKey:kAddressBook];
        }
        addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        if (addressBook != nil) {
            if ([NSThread isMainThread]) {
                ABAddressBookRegisterExternalChangeCallback(addressBook,_ExternalChangeCallback, nil);
            }

            [NSThread currentThread].threadDictionary[kAddressBook] = (__bridge id) addressBook;
            [NSThread currentThread].threadDictionary[kAddressBookGeneration] = [NSNumber numberWithUnsignedLongLong:lastAddressBookGeneration];
        }

    }
    return addressBook;
}

I looked around SO and found the problem could be ABAddressBookCreateWithOptions(NULL, NULL); I probably need to call CFRelease() after calling that. But then, my next question came up: in this method, I need to return addressBook. How can I achieve both 1) return the ABAddressBookRef 2) properly call CFRelease() so I don't get the memory leak warning?

Does this make any sense?

+ (ABAddressBookRef)getABAddressBookRef {
    unsigned long long lastAddressBookGeneration = _addressBookGeneration;
    unsigned long long addressBookGeneration =[[NSThread currentThread].threadDictionary[kAddressBookGeneration] unsignedLongLongValue];
    ABAddressBookRef addressBook = (__bridge ABAddressBookRef)[NSThread currentThread].threadDictionary[kAddressBook];

    if (addressBook == nil || (addressBookGeneration != lastAddressBookGeneration)) {
        if (addressBook) {
            if ([NSThread isMainThread]) {
                ABAddressBookUnregisterExternalChangeCallback(addressBook,_ExternalChangeCallback, nil);
            }
            [[NSThread currentThread].threadDictionary removeObjectForKey:kAddressBook];
        }
        ABAddressBookRef newAddressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        addressBook = newAddressBook;
        if (newAddressBook != nil) {
            if ([NSThread isMainThread]) {
                ABAddressBookRegisterExternalChangeCallback(newAddressBook, _ExternalChangeCallback, nil);
            }

            [NSThread currentThread].threadDictionary[kAddressBook] = (__bridge id) newAddressBook;
            [NSThread currentThread].threadDictionary[kAddressBookGeneration] = [NSNumber numberWithUnsignedLongLong:lastAddressBookGeneration];
            CFRelease(newAddressBook);
        }
    }
    return addressBook;
}

回答1:


you can simulate autorelease easily

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{
    CFRelease(newAddressBook);
});


来源:https://stackoverflow.com/questions/22600766/whats-the-correct-way-of-releasing-an-object-when-it-also-needs-to-be-returned

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!