【问题标题】:Memory allocation / release for NSStringNSString 的内存分配/释放
【发布时间】:2011-06-09 05:36:12
【问题描述】:

我有一个采用MKAnnotation 协议的类。除了要实现的两个“title”和“subtitle”方法之外,我还想添加两个 NSString,一个代表典型美国地址中的每一行。例如:

addressLine1 = 123 street
addressline2 = northridge, ca 91326

我的字幕方法目前看起来像:

- (NSString *)subtitle {
    NSMutableString * ret = [NSMutableString stringWithCapacity:kDefaultStringCapacity];
    if (streetAddress) {
        [ret appendString:streetAddress];
        addressLine1 = [[NSString alloc] initWithFormat:streetAddress];
    }
    ... more code

我什么时候发布 addressLine1?因为它是我用 (nonatomic, retain) 声明的属性,所以我已经在我的 dealloc 方法中释放了它。或者我是使用类方法还是自动释放字符串?谢谢。

【问题讨论】:

  • 为什么要使用没有附加参数的格式?如果没有额外的参数,它实际上并没有做任何事情,只是按原样复制格式字符串,并且 streetAddress 中任何 % 格式说明符的存在都可能会使您的应用程序崩溃。你想在那里完成什么?

标签: iphone objective-c memory-management


【解决方案1】:

如果您autoreleaseaddress1,您将失去该对象的所有权,并且没有任何其他所有者,它将被释放。如果你正在这样做,你需要autorelease它,

self.address1 = [[NSString alloc] initWithString:streetAddress];

这是错误的,因为您会在 dealloc 方法中获得两次所有权并仅放弃一次所有权。正确的方法是,

self.address1 = [[[NSString alloc] initWithString:streetAddress] autorelease];

上面的直接赋值只有在被赋值一次时才有效。如果要再次分配它,您将丢失对较早引用的引用,并且您的应用程序将泄漏。因此,在这里使用属性访问器将是一个很好的过程,这将确保旧值被释放。

字符串的另一件事是你会复制它们,因为你不希望它们在赋值后发生变化,所以属性应该声明为@property (nonatomic, copy),而不是现在的。

【讨论】:

  • 通过使用copy而不是retain,没有必要使用+alloc/-init…——OP可以使用self.address1 = streetAddress代替(假设他使用+alloc/-init来避免引用相同的字符串streetAddressself.address)。
  • 请注意,Crystal 使用了 -initWithFormat: - 尽管以一种相当无意义的方式,正如我在上面的评论中所说的那样。将属性声明为副本,并假设示例中使用的格式字符串只是一个错字,self.address1 = streetAddress 会更直接。
  • 是的,我只是回来补充。不需要alloc-init。如果有 initWithFormat: 是有道理的,但在这种情况下,stringWithFormat: 将是正确的选择。
【解决方案2】:

如果您的属性是(nonatomic, retain),那么如果您没有明确地release 它,您将泄漏addressLine1 资源。我会在你完成后立即发布它。然后应该像您当前所做的那样在您的 dealloc 方法中释放该属性。

与该问题有些无关但仍然相关的是,只要您有一个实现NSCopying 协议的对象,例如在这种情况下为NSString,您应该使用copy 而不是retain。这是一个 SOquestion,它提供了一些很好的信息。

【讨论】:

  • 如果他使用点语法来设置属性,那 泄漏。这样做会通过访问器,正如您所说,除了 +alloc 中隐含的保留之外,它还会添加一个额外的保留。 -dealloc 中只有一个版本,这确实是一个泄漏。但是他没有使用点语法——他直接分配给addressLine1 ivar,绕过了setter和它的retain。因此,-dealloc 中的一个版本就是所需要的,甚至是允许的。
  • @Sherm 除非-subtitle 被多次调用(并输入if),在这种情况下,OP 需要释放前一个对象。
  • 真的,真的。我会使用点语法,并为不暗示所有权的字符串使用“方便”构造函数,如self.addressLine1 = [NSString stringWithFormat:streetAddress]。我也想知道使用格式的意义是什么,当它后面没有参数时......
  • @Sherm/@Bavarious 你说得对。我假设当 OP 提到她使用点语法设置属性的属性时。感谢您指出我的错误。
猜你喜欢
  • 2014-04-02
  • 2011-12-09
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多