【问题标题】:When to make object nil and when to call release何时使对象为零以及何时调用释放
【发布时间】:2011-09-06 05:37:12
【问题描述】:

今天我看到代码中用户首先释放对象,然后他使该对象为零。像这样

[objectA release];
objectA=nil;

我读过很多书,我们应该在离开视图时将对象设为 nil,然后再释放对象(在 dealloc 方法中,这个方法当然是在 viewWillDisappear 或 viewDidDisappear 之后调用的)。

现在我想知道哪种方法更好?

【问题讨论】:

    标签: ios objective-c cocoa-touch memory-management


    【解决方案1】:

    设置为nil 和释放是两个不同的操作。

    release 放弃对一个对象的所有权。这在标准Memory Managemange Guidelines 中有介绍。如果您不熟悉它们,则应在进行任何进一步的 iOS 编程之前阅读它们。

    释放对象后,如果您知道其他代码稍后可能会尝试访问该变量,则应将其设置为nil。这在实例变量中最为常见。

    例如,您可以使用实例变量来存储某种缓存:

    - (NSArray *)items
    {
        if (!cachedItems) {
            cachedItems = [[self calculateItems] retain];
        }
    
        return cachedItems;
    }
    

    稍后您可能需要清除此缓存:

    - (void)invalidateCache
    {
        [cachedItems release];
        cachedItems = nil;
    }
    

    我们需要将 cachedItems 设置为 nil,因为我们的 items 方法可能稍后会尝试使用它。如果我们将其设置为nil,则发送到(现已发布的)缓存的消息可能会导致崩溃。

    因此,当您的类中的其他方法可能在稍后的某个时间点访问该变​​量时,在释放它之后将其设置为 nil。

    【讨论】:

    • 你对第二种情况的解释是什么。先将对象置零,然后释放它,效果和你已经解释的一样吗?
    • 它之所以有效,是因为除了您使用 self.object = nil 的 dealloc 方法之外的任何地方。这使用设置器(如果正确声明)将释放当前值,然后将新值设置为nil。在dealloc 中不要这样做,因为不鼓励在initdealloc 中使用访问器方法。
    • 如果先将变量设置为 nil,然后再释放,则存在内存泄漏。将变量设置为 nil 后,调用 'release' 将无济于事。
    【解决方案2】:

    我认为将对象设置为 nil 并不重要,但这样做很好。

    如果你这样做:

      objectA = nil;
      [objectA release];
    

    您丢失了内存,这是内存泄漏。如果你只做[objectA release],你会释放内存,但是objectA仍然指向内存,所以如果你尝试做这样的事情:

      if (objectA==nil)
    

    这将返回 FALSE,因为 objectA 不是 nil。但是因为你几乎在

      - (void)dealloc;
    

    您不需要在此函数中将其设置为 nil。

    【讨论】:

      【解决方案3】:

      如果对象是在本地创建的:

      我会采用第一种方法,通常的做法是先释放对象然后分配 nil。

      我还没有在任何书中读到过你的第二种方法。

      如果对象是类变量的一部分并且有retain@synthesize

      下面将同时完成这两项工作(第一次发布,然后通过 setter 函数分配nil)。

      self.object = nil ;
      

      【讨论】:

        【解决方案4】:

        第一种方法是适合你的方法..

        [objectA release];
        objectA=nil;
        

        另外,将对象设为 nil 也是一个好习惯(如果您以后使用它,则不是),因为在释放对象后,如果我不小心再次引用它,您的应用程序将会崩溃。但是如果你给对象赋了 nil,然后你在后面引用它,它就不会在目标 C 中崩溃。(类似的情况在 java 等语言中给出了 nullpointerException)

        [objectA doneSomeTask];
        

        不会崩溃,即使 objectA 为 nil。由于目标 C 默默地忽略了对 nil 的引用。

        【讨论】:

        • 发布后是否设置变量为nil存在分歧。如果您希望对象有效,将其设置为nil 可能会隐藏错误。当然,如果错误隐藏得如此之好,以至于没有人注意到它们,那为什么还要费心修复它们,对吧?
        • 我听说过这种分歧@kubi ..我通常做的是评论这些语句,我们在调试期间将变量设置为 nil ......在发布之前取消注释它们..设置所有当我们无法控制在用户设备上运行的程序时,在发布后抑制错误的可能方法..
        【解决方案5】:

        您在书中读到的内容不起作用。如果将对象设置为 nil,则以后不能释放它,因为那时您不能超出该对象。你应该采用第一种方法。

        【讨论】:

        • 在这种情况下,您将发布消息发送到 nil,这将做...除了造成内存泄漏之外什么都没有。另请参阅 Rodrigo 的回答。
        【解决方案6】:

        最好的方法:

        [objectA release]; // sightly sightly faster since less function calls
        objectA=nil;
        

        懒惰的方式:

        self.objectA=nil;
        

        它会调用:

        (void)setObjectA:(ObjectAClass *)objectA
        {
            [objectA release];         // <-- original value is released
            objectA = [objectA retain];// <-- set the point to nil and do nothing since nil
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-04-30
          • 2013-11-19
          • 2011-09-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-24
          • 1970-01-01
          相关资源
          最近更新 更多