【问题标题】:Dealloc method in iOS and setting objects to niliOS中的Dealloc方法并将对象设置为nil
【发布时间】:2011-10-10 08:44:12
【问题描述】:

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

【问题讨论】:

    标签: objective-c ios memory-management dealloc


    【解决方案1】:

    解除分配的三种方法

    1.只需释放

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

    现在对象引用指向一个随机位置,这可能是以下两种情况之一:

    1. 很可能是垃圾,因为内存位置不能解释为对象。
    2. 很少会是不同的对象,因为内存已被重用于创建新对象。

    通过这个指针进一步调用方法的效果是这三个之一(其中一个是未定义的):

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

    2。释放和无

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

    现在对象引用为零,任何进一步的方法调用都将被忽略。这可能会默默地在您的代码中造成已定义但无法预料的横向效应,但至少不会使您的应用程序崩溃。

    3. Nil 和释放

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

    这与以前相同,但它删除了 release 和 nil 之间的那个小窗口,其中对象引用指向无效对象。

    哪个最好?

    这是一个选择的问题:

    • 如果您宁愿崩溃,请选择释放。
    • 如果您宁愿忽略错误,请选择 nil+release 或 release+nil。
    • 如果您使用的是NSZombieEnabled=TRUE,那么只需释放,不要将僵尸归零!

    宏和僵尸

    延迟选择的一种简单方法是使用宏。取而代之的是 [airplane release] 您编写 safeRelease(x) 其中 safeRelease 是您添加到 .pch 目标文件的以下宏:

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

    这个宏不尊重僵尸。这是问题所在:当NSZombieEnabledTRUE 时,对象变成NSZombie。如果您将其对象引用设为 nil,则发送给他的任何调用都将被忽略。

    为了解决这个问题,这里有一个来自Kevin Ballard 的宏,它仅在NSZombieEnabledFALSE 时将指针设置为无效的组合引用。如果没有启用僵尸,这可以保证在调试期间崩溃,否则会留下僵尸。

    #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
    

    参考文献

    Apple 没有关于哪个最好的建议。如果您想阅读社区的想法,这里有一些链接(评论线程也很棒):

    【讨论】:

    • 这是一个很好的答案。谢谢!
    • “在这种情况下你的应用程序崩溃”在什么情况下你的应用程序崩溃了? “你的电话崩溃了”什么电话?我没有看到有人询问任何电话
    • 我指的是(在我的脑海中)释放指针上的方法调用。我为澄清而进行了编辑。
    • 推荐你在ios7中使用arc。你不能调用 dealloc
    • 在 dealloc 的实现中,不要调用超类的实现。 developer.apple.com/reference/objectivec/nsobject/…
    【解决方案2】:

    这个 sn-p 涵盖了所有基础,并且可以剪切和粘贴.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,但添加了文档并符合 Google's coding standards

    【讨论】:

      【解决方案3】:

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

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

      抱歉,笼统地说。

      【讨论】:

      • "如果在多个地方有一个 dealloc 调用" "dealloc 在多个地方调用"是什么意思?你不应该打电话给dealloc
      • 写这个答案时,你应该:) 自动引用计数 (ARC) 并不总是存在。
      • 不,你不应该自己打电话给dealloc,除了[super dealloc]
      【解决方案4】:
      - (void)dealloc
      {
           [searchPlace release];
           [super dealloc];
      }
      - (void)viewDidUnload
      {
           [super viewDidUnload];
           self.searchPlace = nil;
      }
      

      像你说的那样吗?

      【讨论】:

        猜你喜欢
        • 2010-12-13
        • 2011-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多