【问题标题】:Which iPhone OS memory management rules and how-to's do you know?您知道哪些 iPhone OS 内存管理规则和操作方法?
【发布时间】:2010-10-21 15:41:41
【问题描述】:

目前我正在跳入被称为“iPhone OS 中的内存管理”的冰冷水中。

这是我学到的一条规则:

每次在我的方法中看到一个alloc,我都会在方法的底部释放对应的变量。

每次我在我的头文件中创建一个 @property(...) 表示复制或保留时,我都会将该变量的释放消息放入 dealloc 方法中。

每次我有一个 IBOutlet 时,我都会做同样的事情。唯一的例外:如果 IBOutlet 有类似 @property(...assign) 的东西,或者换句话说:如果它有 assign 关键字。那我就不关心在dealloc方法中释放了。

我觉得还有很多好的规则要知道!只要写下你有什么。让我们一起刮掉它们。也欢迎提供精彩描述的链接。

【问题讨论】:

  • 我也很想知道这些规则中的哪些直接适用于 Cocoa(与 Cocoa Touch 相对),哪些适用不同。

标签: iphone objective-c memory-management uikit


【解决方案1】:

实际上,每当您初始化一个对象并且方法名称包含“init”时,您都有责任释放它。如果您使用不包含单词“init”的 Class 方法创建对象,那么您不会。

例如:

  NSString *person = [NSString stringWithFormat:"My name is %@", name];

不需要发布。但是:

  Person *person = [[Person alloc] init];

需要发布(如您在问题中所述)。同样:

  Person *person = [[Person alloc] initWithName:@"Matt"]];

也需要发布。

这是一个约定,而不是语言规则,但您会发现它适用于所有 Apple 提供的 API。

【讨论】:

  • 您的第三个示例甚至不应该存在:初始化方法不应该是静态的,因此应该在已经分配了 alloc 的对象上调用它们。是的,这只是惯例,但这是有充分理由的惯例。静态方法返回自动释放的对象,alloc-init 返回一个保留的对象。
  • @Tony:在第三个示例中看起来像是一个错字,因为括号不匹配。什么时候方法是静态方法?如果没有静态关键字(例如在 Java 中),我如何看到它?
  • 你们俩都是对的,我严重打错了第三个例子。这就是我在网络浏览器中从内存中输入的结果。修复它。
  • @mmc: 第一个例子对 NSString 是否也有效 *str = [NSString stringWithFormat:"My name is %@", name]; (如果我将其分配给 NSString 变量)?
  • 是的,我很高兴我们的想法是一样的。当您输入您的评论时,我编辑了第一个示例以使其更加清晰 :) 我的代码日非常糟糕,即使在工作中调试 aspx 错误页面...也许我今天不应该再回答任何问题了 :)
【解决方案2】:

我使用的规则

  • 释放您使用名称以“alloc”或“new”开头或包含“copy”的方法创建的所有对象。

  • 释放您保留的所有对象。

  • 不要释放使用 +className 便利构造函数创建的对象。 (类创建它并负责释放它。)

  • 不要释放您以其他方式收到的物品,例如 mySprockets = [小部件链轮];

  • 如果您将收到的对象存储在实例变量中,请保留或复制它。 (除非它是弱引用——只是指向另一个对象的指针,通常是为了避免循环引用。)

  • 接收到的对象(通常)在接收它们的方法中有效,并且如果传递回调用者也是有效的。

一些不错的链接:

  1. http://www.gehacktes.net/2009/02/iphone-programming-part-2-objective-c-memory-management/
  2. http://mauvilasoftware.com/iphone_software_development/2008/01/iphone-memory-management-a-bri.html

【讨论】:

    【解决方案3】:

    当您看到每个看似无辜的代码行都出现段错误时,内存管理似乎令人生畏,但一旦掌握了它,它实际上就很容易了。花一点时间阅读this page,然后阅读Apple's documentation,您应该很快就能编写出没有错误的代码了。

    【讨论】:

      【解决方案4】:

      我倾向于只创建自动释放的对象,要么使用类方法,要么在创建后立即自动释放它,除非我可以说明不这样做的理由。例如:

      • 我将它分配给一个成员变量,因为我打算保留它一段时间。
      • 我创建它只是为了立即将其传递给另一个方法,并在该方法调用后立即向它发送一条释放消息。
      • 出于性能原因,我需要在最近的 NSAutoreleasePool 释放之前释放该内存,例如在循环内创建大量对象或对象持有大量数据(例如图像)。

      这样,我不太可能泄漏对象。默认情况下,我创建它们是自动释放的,当我故意决定不自动释放它们时,我立即面临它们将在哪里释放的问题。

      对于对象属性,我喜欢将 nil 分配给它们,而不是在我的 dealloc 方法中释放它们。这样,保留或复制的属性会被发送一个版本,而分配的属性会被简单地覆盖,并且如果我将属性更改为保留属性或从保留属性更改,我不必更新我的 dealloc 方法。

      【讨论】:

      • 在 dealloc 中分配 nil(而不是调用 release)是不受欢迎的,因为如果另一个对象为 KVO 通知注册,或者您编写一个尝试使用另一个实例变量的自定义 setter 方法(可能已经被消灭了)。
      • 我曾经这样做过,但我最终决定在自动释放池中拥有大量对象使得很难弄清楚发生了什么。现在我在任何地方都使用 alooc/init 和 release,除非它无能为力。
      • @Marc:我没有考虑过,感谢您指出这一点。我认为这在内存管理中值得一提:避免析构函数中的副作用(dealloc 方法)。
      猜你喜欢
      • 2011-11-22
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      相关资源
      最近更新 更多