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

Objective c iOS中的Dealloc方法并将对象设置为nil,objective-c,ios,memory-management,dealloc,Objective C,Ios,Memory Management,Dealloc,我有一个很基本的问题。在我看到的一些示例中,对象只是在dealloc方法中释放的。在其他情况下,对象被释放,然后设置为nil。这有什么原因吗?释放后是否设置为nil?如果在多个位置有一个dealloc调用,则将对象变量设置为nil可确保不会多次错误地将其释放。如果从多个位置调用带有dealloc的函数,或者可以由外部代码(即其他类)任意调用,则逻辑相同 在现实生活中,当封闭对象是“可重用的”——支持多轮内容初始化/拆卸时,通常会发生这种情况。对象指针的nil-ness然后成为对象状态的一个有价值

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

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

在现实生活中,当封闭对象是“可重用的”——支持多轮内容初始化/拆卸时,通常会发生这种情况。对象指针的
nil
-ness然后成为对象状态的一个有价值的组件-这意味着对象现在是“空的”

抱歉这么笼统

- (void)dealloc
{
     [searchPlace release];
     [super dealloc];
}
- (void)viewDidUnload
{
     [super viewDidUnload];
     self.searchPlace = nil;
}
这和你说的一样吗?

有三种方法可以解除锁定 1。只需释放

- (void)dealloc {
    [airplane release];
    [super dealloc];
}
- (void)dealloc {
    id temp = airplane;
    airplane = nil;
    [temp release];
    [super dealloc];
}
现在,对象引用指向一个随机位置,这可能是以下两种情况之一:

  • 很可能是垃圾,因为内存位置不能解释为对象
  • 它很少是一个不同的对象,因为内存已被重用以创建一个新对象
  • 通过此指针进一步调用方法的效果是以下三种方法之一(其中一种未定义):

    • 由于指针指向垃圾,导致
      EXC\u BAD\u ACCESS
      崩溃
    • 具有未定义选择器的崩溃,因为它指向没有该方法的有效对象
    • 方法执行成功,因为新对象具有同名的方法
    2。释放和无

    - (void)dealloc {
        [airplane release], airplane = nil;
        [super dealloc];
    }
    
    现在,对象引用为nil,将忽略任何进一步的方法调用。这可能会在您的代码中悄悄地导致一个已定义但无法预见的横向效果,但至少不会使您的应用程序崩溃

    3。零和释放

    - (void)dealloc {
        [airplane release];
        [super dealloc];
    }
    
    - (void)dealloc {
        id temp = airplane;
        airplane = nil;
        [temp release];
        [super dealloc];
    }
    
    这与之前相同,但它删除了对象引用指向无效对象的release和nil之间的小窗口

    哪一个最好? 这是一个选择的问题:

    • 如果你宁愿崩溃,选择释放
    • 如果您宁愿忽略错误,请选择nil+release或release+nil
    • 如果您使用的是
      NSZombieEnabled=TRUE
      ,则只需释放,不要禁用僵尸
    宏与僵尸 推迟选择的一个简单方法是使用宏。您可以编写
    safeRelease(x)
    ,其中safeRelease是添加到.pch目标文件中的以下宏:

    #ifdef DEBUG
      #define safeRelease(x) [x release]
    #else
      #define safeRelease(x) [x release], x=nil
    #endif
    
    此宏不尊重僵尸。问题是:当
    NSZombieEnabled
    TRUE
    时,对象将变成
    NSZombie
    。如果将其对象引用设为零,则发送给他的任何调用都将被忽略

    为了解决这个问题,这里有一个宏,它只在
    NSZombieEnabled
    FALSE
    时才设置指向无效虚构引用的指针。如果未启用僵尸,这将保证在调试期间崩溃,但如果未启用僵尸,则会导致僵尸崩溃

    #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
    
    工具书类 苹果没有推荐哪一个是最好的。如果你想阅读社区的想法,这里有一些链接(评论线程也很棒):

    • 杰夫·拉马尔奇
    • 丹尼尔·贾库特
    • 杰夫·拉马尔奇
    • 黄清兰
    • 乌利·库斯特雷

    此代码段涵盖了所有的基本内容,可以将其剪切粘贴到
    .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
    

    该代码在功能上等同于Jano的第二个版本的
    safeRelease
    ,但增加了文档和遵从性。

    这是一个很好的答案。非常感谢。“在哪种情况下你的应用程序崩溃”在哪种情况下你的应用程序崩溃?“你的电话崩溃了”什么电话?我没有看到任何人询问callI(在我脑海中)对释放指针的方法调用。我编辑是为了澄清。建议您在ios7中使用arc。不能在dealloc的实现中调用deallocIn,不要调用超类的实现。“如果在多个地方有dealloc呼叫”是什么意思?您不应该调用
    dealloc
    在编写此答案时,您应该:)自动引用计数(ARC)并不总是存在。不,您不应该自己调用
    dealloc
    ,除了
    [super dealloc]