简体   繁体   English

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

[英]Dealloc method in iOS and setting objects to nil

I have a pretty basic question.我有一个非常基本的问题。 In some examples I've seen, objects are just released in the dealloc method.在我见过的一些例子中,对象只是在 dealloc 方法中释放。 In others, the objects are released and then set to nil .在其他情况下,对象被释放,然后设置为nil Is there a reason for this?是否有一个原因? Is setting to nil after releasing advantageous?释放后设置为零是否有利?

Three ways to dealloc解除分配的三种方法

1. Just release 1. 刚刚发布

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

Now the object reference points to a random position, which may be one of two things:现在 object 参考指向随机 position,这可能是以下两种情况之一:

  1. Most likely it is garbage, because the memory position can't be interpreted as an object.很可能是垃圾,因为 memory position 不能解释为 object。
  2. Rarely it will be a different object, because memory have been reused to create a new object.很少会是不同的 object,因为 memory 已被重用于创建新的 object。

The effect of a further method calls through this pointer is one of these three (which one is undefined):通过此指针调用进一步方法的效果是以下三个之一(其中一个未定义):

  • A crash with EXC_BAD_ACCESS because the pointer points to garbage.由于指针指向垃圾而导致EXC_BAD_ACCESS崩溃。
  • A crash with undefined selector because it points to a valid object which doesn't have that method.未定义选择器的崩溃,因为它指向没有该方法的有效 object。
  • A successful method execution because the new object has a method by the same name.一个成功的方法执行,因为新的 object 有一个同名的方法。

2. Release and nil 2.释放和零

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

Now the object reference is nil and any further method calls are ignored.现在 object 引用为零,任何进一步的方法调用都将被忽略。 This may silently cause a defined but unforeseen lateral effect in your code, but at least it doesn't crash your application.这可能会在您的代码中默默地导致定义但无法预料的横向效应,但至少它不会使您的应用程序崩溃。

3. Nil and release 3. Nil 和释放

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

This is the same as before, but it removes that small window between release and nil where the object reference points to an invalid object.这与以前相同,但它删除了 release 和 nil 之间的小 window,其中 object 引用指向无效的 object。

Which one is best?哪个最好?

It is a matter of choice:这是一个选择问题:

  • If you rather crash choose just release.如果您宁愿崩溃,请选择仅发布。
  • If you rather ignore the mistake choose nil+release or release+nil.如果您宁愿忽略错误,请选择 nil+release 或 release+nil。
  • If you are using NSZombieEnabled=TRUE then just release, don't nil the zombie!如果您使用的是NSZombieEnabled=TRUE则只需释放,不要将僵尸归零!

Macros and zombies宏和僵尸

A easy way to defer your choice is using a macro.推迟选择的一种简单方法是使用宏。 Instead [airplane release] you write safeRelease(x) where safeRelease is the following macro that you add to your.pch target file:相反[airplane release]您编写safeRelease(x)其中 safeRelease 是您添加到 your.pch 目标文件的以下宏:

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

This macro doesn't respect zombies.这个宏不尊重僵尸。 Here is the problem: when NSZombieEnabled is TRUE the object turns into a NSZombie .这是问题所在:当NSZombieEnabledTRUE时, object 变成NSZombie If you nil its object reference, any call sent to him will be ignored.如果您将其 object 引用设为 nil,则发送给他的任何呼叫都将被忽略。

To fix that, here is a macro from Kevin Ballard that sets the pointer to an invalid made up reference ONLY when NSZombieEnabled is FALSE .为了解决这个问题,这里有一个来自Kevin Ballard的宏,它仅在NSZombieEnabledFALSE时将指针设置为无效的虚构引用。 This guarantees a crash during debug time if zombies are not enabled, but leaves the zombies be otherwise.如果没有启用僵尸,这可以保证在调试期间崩溃,否则会留下僵尸。

#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

References参考

Apple doesn't have a recommendation on which one is best.苹果没有推荐哪一个是最好的。 If you want to read the thoughts of the community here are some links (the comment threads are great too):如果您想阅读社区的想法,这里有一些链接(评论线程也很棒):

This snippet covers all the bases and is ready to cut and paste into a .pch file.该片段涵盖了所有基础可以剪切并粘贴.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

The code is functionally equivalent to Jano's second version of safeRelease , but adds documentation and compliance with Google's coding standards .该代码在功能上等同于 Jano 的第二版safeRelease ,但增加了文档并符合Google 的编码标准

If there's a dealloc call in more than one place, setting the object variable to nil makes sure it won't be deallocated more than once by mistake.如果在多个地方有一个dealloc调用,将 object 变量设置为 nil 可以确保它不会被错误地释放多次。 Same logic if the function with the dealloc is called from more than one place, or can be called arbitrarily by external code (ie other classes).如果dealloc从多个地方调用,或者可以通过外部代码(即其他类)任意调用,则相同的逻辑。

In real life, this typically happens when the enclosing object is "reusable" - supports multiple rounds of content initialization/teardown.在现实生活中,这通常发生在封闭的 object 是“可重用”的 - 支持多轮内容初始化/拆卸时。 The nil -ness of object pointers then becomes a valuable component of object state - it means that the object is "empty" right now. object 指针的nil成为 object state 的重要组成部分 - 这意味着 ZA8CFDE633111BD59EB2AC96B88 现在是空的。

Sorry for the generalities.抱歉笼统地说。

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

Is this like what you say?这和你说的一样吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM