【问题标题】:@property retain - iPhone@property 保留 - iPhone
【发布时间】:2011-06-09 04:33:31
【问题描述】:

我是 iPhone 编程的新手。我有以下疑问阻止我继续前进。请考虑以下代码:

---------.h------
@interface myClass: UIViewController
{
    UIImage *temp;
}

@property (nonatomic, retain) UIImage *temp;

 ---------.m------
 @interface myClass
 @synthesize temp;

 -(void) dealloc
 {
   [temp release];
   [super dealloc];
 } 
  1. 以上是唯一的程序代码。就是这样……没有别的了。即使我根本没有在我的程序中使用属性访问器方法,我是否需要在 dealloc 方法中声明 [temp release]。如果我不在 dealloc 中声明 [temp release] 怎么办。这会造成内存泄漏,因为我正在释放我没有保留的东西,因为我没有调用属性访问器方法。

  2. 另外,当我打印 temp 的保留计数时,为什么它显示为 0,即使它被保留在 @property 中。

提前致谢

【问题讨论】:

    标签: iphone objective-c properties retain


    【解决方案1】:
    1. 如果从未为 myClass.temp(的实例)分配任何值,则不会发生泄漏。但是你应该在你的 dealloc 中释放它。

    2. @property 只是声明 myClass 的实例将具有此属性。您需要在保留该值之前为其分配一个值。

      myClass *instance = [[myClass alloc] init];
      
      // instance will now retain the value passed in
      // and is therefore responsible for releasing it
      instance.temp = [UIImage imageNamed:@"whatever"];
      
      // if instance is not retained anywhere else,
      // its dealloc will be called
      [instance release];
      

    在旁注中,你应该给你的类名以大写开头 信,即MyClass。不是必需的,但会让事情更清楚。

    你也可以在你的dealloc 中使用self.temp = nil; 你有点不应该,但它有点效果更好,看起来更干净。这是一个有点不确定的主题......

    【讨论】:

      【解决方案2】:

      你所做的是正确的。滚动到此 Apple Doc 的“dealloc”部分:Declared Properties

      不过,很快,当您合成这些属性时(在下一次 Cocoa 更新中),这些属性将被自动清理——话虽如此,我个人已经开始遵循一个约定,以便我的代码在未来可以工作,即设置 @ 987654323@ 在 dealloc 中而不是发送发布消息(阅读我发布的苹果文档,它解释了这一点)。在运行时创建的访问器方法首先释放对象,所以对于我和其他一些开发人员来说,这是清理我们的 dealloc 中声明的属性的更好/更安全的方法。

      【讨论】:

      • 这也适用于 iOS 开发吗??
      • 在 dealloc 中使用该属性并不是一个好主意。目前建议您发布 ivar。这是为了防止您意外调用子类覆盖和意外触发 dealloc 中的 KVO 通知。
      • “不过,很快,这些属性将在您合成它们时自动清理(在下一次 Cocoa 更新中)”。呃,什么?
      • 我指的是 ARC 谣言。
      【解决方案3】:

      你的代码是正确的。

      一般规则是,对于您在@interface 中声明的所有变量,您必须在-dealloc 中清理它们。一些变量需要被释放,其他的只需要被 nil'd,这取决于你如何声明 @property。

      在你上面的例子中,temp 可能从来没有被你明确地赋予一个值,但是当一个实例时,ObjC 运行时会将 temp 的值初始化为 nil你的班级被分配了。

      向 nil 对象发送 -release 通常不是问题,因此 [temp release] 很好。这是一个无操作。当 temp-dealloc, 中具有非零值时,[temp release] 开始释放内存。

      如果您需要 temp 在创建时具有非零值,则需要实现 -init 方法并确保它获得一些值。虽然您的类在没有 -init 方法的情况下是合法且实用的,但您确实应该养成习惯,在您设计的每个自定义类中都包含一个。

      您至少需要默认初始化程序:-init。您可能还想设计一个更详细的初始化程序,可用于为您的 temp ivar 提供一个值,例如 -initWithImage:

      您还应该在课堂上包括以下内容:

      @implementation MyClass
      
      ...
      
      - (id) init {
         self = [super init];
         if (self != nil) {
            // The minimal default initializer.
            // temp will already have a value of nil, so you don't need necessarily 
            // need to do anything more, unless temp needs a real value on initialization.
         }
         return self;
      }
      
      - (void) dealloc {
      ...
      }
      

      @结束


      要实现一个更详细的初始化器,称为 designated 初始化器,您可以这样:

      @implementation MyClass
      
      ...
      
      - (id) initWithImage:(UIImage *)newImage {
         self = [super init];
         if (self != nil) {
            temp = [newImage retain];
         }
         return self;
      }
      
      // Implement the default initializer using your more detailed initializer.
      
      - (id) init {
         // In this default initializer, every new instance comes with a temp image!
         return [self initWithImage:[UIImage imageNamed:@"foobar"]];
      }
      
      - (void) dealloc {
      ...
      }
      @end
      

      这里,指定初始化器-initWithImage:是权威初始化器。所有其他初始化程序,包括 -init,都使用 -initWithImage: 实现。

      您可以自行决定是否实现超出最小默认初始值设定项的任何初始值设定项。也许-init 足以满足您的目的。没关系。有时更详细的初始化器使使用类更方便。经验(和原力)将成为您的向导。

      请注意,我没有在任一初始化方法中使用生成的属性访问器。如果环境不要求您,您通常应避免在 -init 方法和 -dealloc 中使用属性访问器,主要是因为自动键值编码通知的副作用可能会带来令人头疼的问题。

      初始化方法和dealloc方法在一个类中扮演着特殊的角色。作为类设计者,您有责任在这些方法中设置和清理实例变量。一个好的经验法则是将合成属性访问器的使用留给类的调用者,以及类中其他方法的实现。

      在初始化实例或解除分配时,您可以而且应该直接接触 ivars。他们是你的。您声明了它们,因此您可以直接处理它们。在您的类中实现其他方法时,您通常应该使用属性访问器。

      JeremyP 的 Cocoa 对象概念文档链接是一个很好的链接。您绝对应该阅读有关对象的部分,并在获得更多编写自己的自定义类的经验时定期重新阅读。最终,一切都会开始变得有意义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-02
        • 2011-12-09
        • 1970-01-01
        • 2010-10-09
        • 2011-07-25
        • 2011-05-14
        • 1970-01-01
        • 2011-11-03
        相关资源
        最近更新 更多