发布,Dealloc和自我参考

时间:2009-07-31 06:49:25

标签: objective-c memory-management null

所以我认为我已经弄明白了所有这些问题。然后突然间我得到一个错误(崩溃)我无法弄清楚。然后在做了研究以解决崩溃之后,我注意到我认为我对这些关键领域知道的一切都有些不对。

以下是我要拍摄的8个问题,希望有人回答 - 这些问题的答案将极大地帮助我恢复理解。提前谢谢!

Q1)如果该引用为零,是否可以在对象上调用Release?这应该是无害的,对吗?

Q2)如果该参考已被释放且参考计数为0,是否可以在对象上调用Release?

Q3)是否有必要在释放之后设置nil的引用?如果你没把它设置为零会发生什么?

Q4)nil和NULL之间是否真的存在差异,或者只是通过浏览它来帮助读者/开发人员了解对象类型只是一种语义?

Q5)使用属性要求使用'Self'指针吗?

Q6)使用实例变量需要不使用'Self'指针?

Q7)我什么时候想要使用实例变量而不是其属性?我认为价值类型数据成员是可以的,因为他们没有发布和保留参与。

Q8)是否有必要在dealloc函数中调用对象的dealloc? 在许多例子中,我看到Release被调用,但不是Dealloc - 这样的教程是不正确的?

5 个答案:

答案 0 :(得分:19)

A1)[nil release]很好(不做任何事)

A2)否。请勿在取消分配后触摸物体。它们被释放后应设为零。

A3)没有必要将释放的指针设置为nil,但是你会得到悬空指针(即,你无法分辨对象是否有效)。将属性设置为nil通常用于释放底层的ivar,因此如果不这样做可能会导致内存泄漏

A4)nil和NULL均为零,因此在技术上是相同的。

A5)是的,您必须使用self.someProperty作为属性,就像使用[self someProperty]一样,如果它只是一种方法

A6)self本质上是一个结构,所以你可以像这样访问ivars:self->someIvar。但是,没有必要。

A7)当你不想因任何原因运行setter / getter方法时。当setter不允许nil值时我偶尔使用它,我需要释放变量

A8)当释放被称为正确的次数时,会自动调用dealloc。你永远不应该直接调用dealloc([super dealloc]除外)

答案 1 :(得分:11)

你应该把这个问题分成几个不同的问题,但我会咬人。

  1. 是的,发送给nil的任何消息都是no-op。
  2. 否。 ref-count为0的对象已经或即将被销毁,发送给它的任何消息都会导致崩溃,或者最多也会导致异常。
  3. 这取决于具体情况。如果您要在-dealloc中发布内容,那么可能不会。如果它是一个作用于特定方法的对象,那么可能不是。如果它是重复使用的ivar,我会说是的。在前两种情况下,如果不将指针设置为nil,则不会发生任何事情,因为您通常无法再访问这些指针。但在最后一种情况下,您仍然可以访问指向已释放内存的指针。如果您发送消息或尝试取消引用它,您的应用程序将崩溃。
  4. 它们都等于0.按惯例,nil用于对象指针,NULL用于任何其他指针,但混合它们不会导致任何问题。
  5. 如果要调用属性getter / setter,则为yes。如果你想访问ivar,它会直接封装(不常见),没有。
  6. 不,您可以使用语法self->ivar访问实例变量。实际上,当您只键入ivar时,编译器会隐式添加self->解除引用。
  7. 不确定你的意思。
  8. 您应该拨打-dealloc的唯一时间是使用您自己的[super dealloc];方法拨打-dealloc。对于任何其他对象,您应该始终只需拨打-release

答案 2 :(得分:8)

其他人已经充分回答了1-6。

(7)Apple建议您在init和dealloc中直接使用实例变量。这主要是因为对象(特别是如果它是子类)在这两个方法中只是部分设置,因此如果它们有除了普通操作以外的任何东西,则调用setter / getter可能会导致错误的行为。一般来说,你可以安全地直接访问你的对象中的ivar(而不是通过getter),这样做会稍微有效(仅限于iPhone上的相关内容)。通常,您应该在所有情况下使用setter,特别是如果您的对象可能是子类,或者其他人可能正在观察该属性。

(8)你永远不会在dealloc方法中调用dealloc(除了[super dealloc])。如果您拥有另一个对象的所有权,那么您应该放弃该所有权(通过调用release或autorelease)。然后,如果合适,系统将在对象上调用dealloc。但你永远不会自己打电话给dealloc。阅读memory management rules(仅有9段,对于理解是至关重要的)。

答案 3 :(得分:0)

确定。我已经确认没有将B设置为nil就可以了。 所以,现在,我在创建B控制器时不检查nil(当我想导航到它时)。

相反,我发布B,然后我创建控制器并将其分配给B. 然后,在A的viewDidAppear方法中,我发布B。

我相信这个帖子现已关闭。谢谢!

答案 4 :(得分:0)

A4)他们的类型不同。它们都为零,但NULL是一个void *,nil是一个id,而Nil是一个Class指针。