1

我有一个访问地址簿的类,如果我有以下代码,那么我会从分析器中收到警告,一个是 init 方法中的泄漏,另一个是说该类在释放对象时不拥有该对象释放。

我认为第二个警告是由于将通讯簿引用声明为分配?但它不可能使它变得强大,因为这会产生一个编译警告。将通讯簿作为财产处理的正确方法是什么?

@property (assign, nonatomic)   ABAddressBookRef                addressBook;

..
- (id) init
{
    self = [super init];
    if (self)
    {
        if (ABAddressBookCreateWithOptions)
        {
            // iOS 6 onwards
            self.addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        }
        else
        {
            // < iOS 6
            self.addressBook = ABAddressBookCreate();
        }
    }
    return self;
}


- (void) dealloc
{
    if (self.addressBook)
    {
        CFRelease(self.addressBook);
    }
}
4

3 回答 3

1

这是一个误报,您正确地平衡了初始 +1retainCount与 dealloc 方法中的CFRelease调用。

您可以通过使用 ivar 而不是属性来初始化和释放指针来消除警告。

- (id) init {
    // ...
    _addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
    //...
}

- (void)dealloc { 
    CFRelease(_addressBook); //assuming that _addressBook is your synthesized ivar
}
于 2013-01-03T22:10:51.323 回答
0

从技术上讲,您不拥有地址簿是正确的,因为assign属性不应该拥有引用。您班级的客户可能会覆盖地址簿参考,而您会泄露它。

完全修复它的一种方法是为您的地址簿明确声明一个字段并为其创建一个只读属性,然后只处理类内部的字段,而不是属性。由于无法分配只读属性,因此毫无疑问它们是否拥有引用。

retain我不在我的 Mac 前,所以我无法对此进行测试,但即使这不是 Objective-C 对象,也可以使用ed 属性。许多Core Foundation 对象以Objective-C 标头开头并响应多种NSObject方法。如果您无法使其与@synthesize.

于 2013-01-03T22:07:15.517 回答
0

这是我使用的解决方案

@synthesize addressBook = _addressBook;
- (ABAddressBookRef)addressBook{
    if (_addressBook == nil){
        if (ABAddressBookCreateWithOptions != NULL){
            _addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
        }
        else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
            _addressBook = ABAddressBookCreate();
#pragma GCC diagnostic pop
        }

        if (![self requestAddressBookAuthorizationWithAddressBook:_addressBook]){
            _addressBook = nil;
        }

    }
    return _addressBook;
}
- (void)setAddressBook:(ABAddressBookRef)addressBook{
    if (_addressBook != addressBook){
        if (_addressBook != nil){
            CFRelease(_addressBook);
        }

        _addressBook = nil;

        if ([self requestAddressBookAuthorizationWithAddressBook:addressBook]){
            _addressBook = addressBook;
        }
        if (_addressBook != nil){
            CFRetain(_addressBook);
        }
    }
}

此时您可以将属性设置为 nil 并且 setter 将处理摆脱保留

于 2013-01-03T22:16:12.100 回答