【问题标题】:Creating a new NSString instance has retain count of 3创建一个新的 NSString 实例的保留计数为 3
【发布时间】:2011-10-01 13:08:46
【问题描述】:

我正在尝试复制一个传递给这样的方法的字符串:

-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
    NSLog( @"elementName, %@:  %i", elementName, [elementName retainCount] ); // rc = 2

    if ( currenttag )
        [currenttag release];

    NSLog( @"currenttag:  %i", [currenttag retainCount] ); // rc = 0

    //currenttag = [[NSString alloc] initWithString:elementName];   // track current element
    [self setCurrenttag:elementName];

    NSLog( @"currenttag:  %i", [currenttag retainCount] ); // rc = 3

    .
    .
    .
    }

setCurrenttag 是合成访问器 (@property (copy))。我的理解是,这将创建一个全新的对象,而不仅仅是对elementName 的引用。上面的行为就好像它保留了对elementName 的引用并调用了retain。被注释掉的代码显示了相同的行为。

这些方法正在实现NSXMLParserDelegate 协议,但我确实需要跟踪某些元素名称(但不是全部)。

关于 iPhone 上的 NSString 对象和内存管理,我有什么遗漏吗?

另外,作为参考,我正在使用 XCode 3.6 的 iPhone 模拟器上运行它。

【问题讨论】:

  • 如果你担心字符串没有被复制,为什么不检查 elementName 和 currenttag 的指针?
  • @Brad Larson 保留计数不是监视内存泄漏的快速方法吗?
  • @Mike - 不。在上面的链接中阅读 Dave 对此的看法。如需更强烈的回应,请参阅:stackoverflow.com/questions/3730804/…。请注意,这两个人都是 Apple 员工。
  • @Brad Larson 感谢您的澄清。

标签: iphone objective-c


【解决方案1】:

对于像 NSString 这样的不可变 Foundation 类,copy 只是保留对象。复制已知不可变的对象会浪费资源,因此不会发生。这在 NSCopying 协议的文档中有所暗示。实现该协议的选项之一是:

  • 通过保留 原创而不是创造一个新的 复制当类及其内容 是不可变的

一般来说,如果您知道某个类的实例是不可变的,那么保留目标对象而不是复制它是完全有效的。

【讨论】:

【解决方案2】:

不要指望retainCount 是直观的。这里可能发生的情况是,有问题的字符串是不可变的,因此“副本”最终只会保留现有的字符串(这很好,因为它永远不会改变)。

【讨论】:

  • @Damiel Dickison 如果我理解正确,发布后,我应该将 currenttag 设置为 nil。
【解决方案3】:

当您处理对象时,您绝不能直接处理保留计数,您必须仅根据差异来处理它们。你必须知道的是,保留是+1,释放是-1

【讨论】:

    【解决方案4】:

    只是一个猜测,但由于 NSString 是不可变的,因此该属性执行 retain 而不是创建新对象可能是一种优化。

    【讨论】:

      【解决方案5】:

      不要相信retainCount。只需释放您为其调用 alloc、copy、retain 和 new 的每个对象。

      【讨论】:

      • 我的问题更多是关于正确实例化一个新字符串。我只使用retainCount 进行调试。我在需要时调用 release,但它的行为方式与 Apple 的内存管理指南描述的不同,除非有特殊部分处理我错过的字符串。
      • 除了我需要跟踪所有元素名称,因为它在文档层次结构中移动。调用 release 后,我无法让它持续存在。
      【解决方案6】:

      根据我的经验,retainCount 并不总是返回实际的保留计数,这可能很棘手。 NSString 是一个不可变对象,因此它的行为可能与其他对象不同,我不确定 Objective C 是否像 java 那样实现了一个字符串池,因为它在文档中没有提到。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-16
        • 2016-11-16
        • 1970-01-01
        • 1970-01-01
        • 2012-05-31
        • 2011-07-21
        • 2013-10-20
        相关资源
        最近更新 更多