【问题标题】:How to release memory of a retained object如何释放保留对象的内存
【发布时间】:2012-03-29 14:10:58
【问题描述】:

这是我的方法之一。

- (void)getSearchResultsByKeyword:(NSString *)keyword 
                searchOptions:(NSArray *)searchOptions 
         searchGroupsInResult:(NSArray *)searchGroupsInResult
{
    _searchKeyword = [keyword retain];
    _searchOptions = [searchOptions retain];
    _searchGroupsInResult = [searchGroupsInResult retain];
    [_searchResultsGroups removeAllObjects];
    [_searchResultsGroupsIndexToNameMap removeAllObjects];
    _pageNo = 1;
    [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:SearchResultsRetrievingStartLodingNotification 
                                                                object:self];
    [_dataProvider startGettingSearchResultsByKeyword:self.searchKeyword 
                                    searchOptions:_searchOptions
                             searchGroupsInResult:_searchGroupsInResult
                                           pageNo:_pageNo
                                         delegate:self];
}

在我的方法中,我对作为参数的对象调用了保留。所以我拥有该对象并增加了保留计数。所以我的问题是,如何在

之后减少保留计数
[_dataProvider startGettingSearchResultsByKeyword:self.searchKeyword 
                                        searchOptions:_searchOptions
                                 searchGroupsInResult:_searchGroupsInResult
                                               pageNo:_pageNo
                                             delegate:self];

打电话。 ([keyword release][_searchKeyword release])??

在我的头文件中,我将_searchOptions 声明为私有实例,并将_searchKeyword 声明为readonly 属性。在我的实现文件中,我在dealloc 中发布了这两个实例。

我运行了分析工具,但它没有将这件事显示为问题。但我对此表示怀疑。

所以,请告诉我处理这件事的必要方法。

我正在开发 XCode4 和 iOS 4.3。

谢谢。

【问题讨论】:

  • 你用[object_address release]释放一个对象。

标签: objective-c ios memory-management xcode4 memory-leaks


【解决方案1】:

jaydee3 的回答是正确的。我要补充一点,您真的应该将@properties 与合成访问器一起使用。然后,不要直接设置实例变量,而是使用访问器方法。这样,您可以将实例变量的所有内存管理封装在访问器方法中。这样做的好处是可读性更高,更不容易出错,并且让您的代码在未来更容易修改。

因此,在您的 .h 中(如果属性应该是“私有”,则在您的 .m 中的类扩展中):

@property (nonatomic, copy) NSString *searchKeyword;

在您的 .m 中:

- (void)dealloc
{
    self.searchKeyword = nil;

    [super dealloc];
}

@synthesize searchKeyword = _searchKeyword;

最后,在您的-getSearchResultsByKeyword:searchOptions:searchGroupsInResult: 方法中:

self.searchKeyword = keyword;

而不是

_searchKeyword = [keyword retain];

现在您不必担心释放保留searchKeyword。 @synthesize 指令生成的 setter 方法将为您处理它。我建议阅读 Apple 在 Declared Properties 上的文档。

【讨论】:

    【解决方案2】:

    由于您要分配给 ivar,因此您必须保留它。这是对的。 在 dealloc 中释放它也是正确的。但这还不够。两件事:

    1) 最好复制字符串,而不是保留它们。所以使用_searchKeyword = [keyword copy];。 (这也是保留的。所以之后retainCount为1。)

    2) 还有一个问题,当你第二次调用你的方法时。这就是你确实有泄漏的地方。您正在为您的 ivar `_searchKeyword' 分配一个新值,取消指向仍然保留的旧关键字的指针。所以在分配新的之前,也要释放旧的。

    例子:

    [_searchKeyword release];
    _searchKeyword = [keyword copy];
    

    如果你复制它,这很好,但如果你只保留,那就更好了(如果两者都引用同一个对象):

    [keyword retain];
    [_searchKeyword release];
    _searchKeyword = keyword;
    

    【讨论】:

    • 感谢 jaydee3。你的回答绝对有帮助。但我还有一个问题。第一次调用'-getSearchResultsByKeyword:searchOptions:searchGroupsInResult:'方法时,'_searchKeyword'的retain count为0。那么在'[_searchKeyword release]'调用之后,会发生什么?
    • 绝对保留计数没有意义; copy 的结果是 +1 保留计数。实际的保留计数可能大不相同。
    • 不幸的是,@bbum,有一个文档错误导致人们引用复制对象的保留计数为 1:“复制对象不仅会复制它,而且几乎总是将其保留计数重置为 1”@ 987654321@,在 Cocoa Fundamentals 中的图 2.5 正下方。
    • 几乎总是 是关键,虽然...应该重新措辞。已提交错误。
    • 无论如何回答你的问题。在 nil 对象上,您可以发送任何消息而无需担心。因此,由于您的 _searchKeyword 一开始是 nil,您可以在其上发送 release 并且什么都不会发生。
    【解决方案3】:

    当有两个对象指向同一个对象时,调用释放对象并不重要。指出的是引用计数减少的地方。

    假设你已经在一个地方发布了它,并且分析器没有抱怨,你没有问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      相关资源
      最近更新 更多