使用ARC的自定义类初始值设定项 - self.name或name?

时间:2012-07-28 18:30:54

标签: objective-c ios5 memory-management

使用ARC定义Person类时,

  1. 我应该在初始化程序中使用 self.fullname 还是 fullname
  2. 如果我使用 fullname ,是否会保留传递的字符串?
  3. 如果我使用 self.fullname 我必须定义一个setter或一个属性吗?我应该使用强大的
  4. Person class initializer

    来自ARC之前思考的方式,我试图围绕ARC建议的变化。

3 个答案:

答案 0 :(得分:3)

  1. 使用ARC,这些行为方式相同,只是self.fullname将通过setter。默认的setter将为您提供KVO合规性。但除此之外,没有区别。
  2. 如果指针被宣布为强大,他们会的。
  3. 要使用self.fullname = ...,您必须定义一个setter。对于NSStrings和其他具有可变变体的类,通常建议使用(copy)

答案 1 :(得分:2)

在初始化器中,我建议反对调用self上的任何方法,因为该对象处于缺乏自我一致性的异常状态。对于您给出的简单示例,它不会立即产生影响。但是,如果您稍后定义了自己的-setFullname:方法来读取或写入对象的任何其他部分,则从初始化程序调用{​​{1}}将导致问题,因为该对象尚未完全形成。

答案 2 :(得分:2)

我认为可用的答案需要一些澄清。

你问题的答案很长

看看这个标题:

Person : NSObject {
    NSString *name; // better to call this _name to not confuse it with the property
    // and even more better to not use an ivar, but only a property
}

@property (strong) NSString *name;
  1. 您有一个实例变量。通常,您使用下划线将您的ivar称为与属性相同,但通常您会发现ivar和该属性具有相同的名称。
  2. 也可以声明属性,在这种情况下,编译器将自动为您插入带有下划线的ivar!
  3. 现在重要的是要理解,name = @"John Smith"self.name = @"John Smith"之间存在一个主要区别,第一个直接设置实例变量(又名_name = @"John Smith",忽略内存管理和(没有ARC)如果前一个值不是nil则创建泄漏。使用self-dot-syntax(self.name)使用自动生成的访问器(= setter方法),它尊重所选的内存管理(通常保留或强或复制)。

    在属性之前和ARC之前,对象设置器看起来像这样:

    -(void)setName:(NSString*)newName {
        if(newName != name) {
            [name release];
            name = newName;
            [newName retain];
        }
    }
    

    这意味着,将释放旧的iVar值并保留新的iVar值。一切都平衡而且很好。

    现在,使用ARC和合成访问器(属性),您不必关心所有这些。当Properties合成acessors时,ARC会根据您的代码分析合成并平衡保留/释放调用。所以ARC和属性并不一定要求彼此,因为它们综合了不同的方面(注意例如不同的语法" __弱"在ivar声明和"(弱)"在属性宣言?)。但知道它如何运作有用,因为现在你会发现它们之间存在重大差异

    name = @"John Smith"; // directly access ivar, the old value is never released 
    // your program is leaking if you're not using ARC
    

    并通过合成访问器

    self.name = @"John Smith"; // old ivar released, new ivar set, all okay
    

    您问题的简短回答

    1. 如果不需要,则不要使用ivar 属性
    2. self.property = newValue通过其setter方法设置新值
    3. ivar = newValue直接设置新值,绕过任何setter方法
    4. 绝对建议使用访问器,如果有setter方法则不直接设置ivars(换句话说:如果你有一个属性,可以通过调用self.property = newValue来使用它的setter)