iOS中的Dealloc方法并将对象设置为nil

我有一个非常基本的问题。 在我看到的一些例子中,对象只是在dealloc方法中被释放。 在其他情况下,对象被释放,然后设置nil 。 是否有一个原因? 释放后是否设置为有利?

三种方式dealloc

刚刚发布

 - (void)dealloc { [airplane release]; [super dealloc]; } 

现在对象引用指向一个随机的位置,这可能是两件事情之一:

  1. 很可能是垃圾,因为内存的位置不能被解释为一个对象。
  2. 很less会是一个不同的对象,因为内存已被重用来创build一个新的对象。

通过这个指针调用的另一个方法的效果是这三个之一(哪一个是未定义的):

  • EXC_BAD_ACCESS崩溃,因为指针指向垃圾。
  • 未定义的select器崩溃,因为它指向一个没有该方法的有效对象。
  • 一个成功的方法执行,因为新对象有一个同名的方法。

2.发布和无

 - (void)dealloc { [airplane release], airplane = nil; [super dealloc]; } 

现在对象引用是零,任何进一步的方法调用被忽略。 这可能默默地在代码中导致定义但不可预见的横向效应,但至less不会导致应用程序崩溃。

3.无和释放

 - (void)dealloc { id temp = airplane; airplane = nil; [temp release]; [super dealloc]; } 

这和以前一样,但是它将删除release和nil之间的小窗口,其中对象引用指向一个无效的对象。

哪一个最好?

这是一个select的问题:

  • 如果你宁愿崩溃select刚刚释放。
  • 如果你宁愿忽略这个错误,请selectnil + release或release + nil。
  • 如果你使用NSZombieEnabled=TRUE那么只要释放,不要僵尸!

macros和僵尸

延迟您select的简单方法是使用macros。 相反[airplane release]你写safeRelease(x) safeRelease是你添加到你的.pch目标文件的以下macros:

 #ifdef DEBUG #define safeRelease(x) [x release] #else #define safeRelease(x) [x release], x=nil #endif 

这个macros不尊重僵尸。 这是问题:当NSZombieEnabledTRUE ,对象变成NSZombie 。 如果你没有它的对象引用,发送给他的任何呼叫都将被忽略。

为了解决这个问题,这里是一个来自Kevin Ballard的macros, NSZombieEnabledNSZombieEnabledFALSE时将指针设置为无效的组合引用。 如果僵尸没有启用,这可以保证在debugging期间发生崩溃,但是会以其他方式离开僵尸。

 #if DEBUG #define safeRelease(x) do { [x release]; if (!getenv("NSZombieEnabled")) x = (id)0xDEADBEEF; } while (0) #else #define safeRelease(x) [x release], x = nil #endif 

参考

苹果没有build议哪一个最好。 如果你想阅读社区的想法这里有一些链接(评论线程也很棒):

  • Dealloc Jeff Lamarche
  • 不要勾引你的代码 Daniel Jalkut
  • 更多关于dealloc Jeff Lamarche
  • 无论是否为零,这就是黄青兰的问题
  • Objective-C中的防御性编码 Uli Kusterer

这个片段涵盖了所有的基础 ,并准备好剪切和粘贴.pch文件。

 // SAFE_RELEASE // Releases an object, then does other things based on context. // // The intention is to fail early during internal testing but prevent // customers from experiencing crashes if at all possible. // // For more information see: // http://stackoverflow.com/questions/6778793/dealloc-method-in-ios-and-setting-objects-to-nil // // Debug build: // If zombies are enabled, the macro just calls |release|. The zombie // mechanism will continue to be used to find messages sent to // the deallocated object. // Otherwise, zombies are not enabled, so the macro sets the object to a // invalid memory address. (0xDEADBEEF.) This will intentionally // cause a crash if the object is used, allowing the bug to be found // and fixed immediately. // // Release build: // The macro calls |release| normally. Then it sets the object to nil to // prevent a possible crash caused by sending a message to a // deallocated object. Messages sent to nil are always allowed. // #if DEBUG #define SAFE_RELEASE(x) \ do { \ [x release]; \ if (!getenv("NSZombieEnabled")) \ x = (id)0xDEADBEEF; \ } while (0) #else #define SAFE_RELEASE(x) \ [x release], x = nil #endif 

该代码在function上等同于safeRelease的第二版safeRelease ,但增加了文档并符合Google的编码标准 。

如果在多个地方有一个dealloc调用,将对象variables设置为零,确保它不会被错误地多次释放。 如果带有dealloc的函数是从多个地方调用的,或者可以通过外部代码(即其他类)任意调用,则是相同的逻辑。

在现实生活中,这通常发生在封闭对象“可重用”时 – 支持多轮内容初始化/拆卸。 对象指针的零度成为对象状态的一个重要组成部分 – 这意味着对象现在是“空的”。

对不起,一般。

 - (void)dealloc { [searchPlace release]; [super dealloc]; } - (void)viewDidUnload { [super viewDidUnload]; self.searchPlace = nil; } 

这就像你说的吗?