@synthesize foo = _foo到底是什么?

时间:2011-09-01 20:32:28

标签: objective-c ios automatic-properties

为什么在iOS应用中需要这个下划线前缀?

4 个答案:

答案 0 :(得分:3)

有时候看看幕后发生的事情是有帮助的。基本上当你看到这个

@property (nonatomic, retain) Foo *foo;

在实施中使用

@synthesize foo=_foo;

以下是语法糖,这意味着编译器基本上为您生成了这段代码

Foo *foo = nil;

-(Foo *) foo {
    return _foo;
}

-(void) setFoo:(Foo *)val {
    if( _foo != val ) {
        [_foo release];
        _foo = [val retain];
    }
}

这种方式当您引用公共属性时,您可以通过 self.foo 生成的附件来查看它,如果您想引用类中的实例变量,可以参考 _foo 即可。在XCode四之前,两者之间很容易混淆。你可以做点什么

self.foo = foo1;

foo = foo2;

这是完全合法的,可能导致几个级别的问题。第二行不使用访问器,因此不会保留foo2,这可能导致垃圾收集过早被拾取。更糟糕的是,第二行不使用会释放任何先前值的访问器,这意味着它会导致内存泄漏。

总而言之,新技术为您的属性创建了一个getter和setter,并允许您指定用于实例变量的名称,用于封装。

答案 1 :(得分:1)

这就是我有时这样做的原因:

如果我想对属性进行延迟加载,我通常会强调我的ivar,以便从后端服务器/已保存文件中加载所需数据的工作/只有你第一次加载。例如:

- (NSMutableArray *)recentHistory;
{
   if (_recentHistory == nil)
   {
       // Get it and set it, otherwise no work is needed... hooray!
   }

   return _recentHistory;
}

所以这里调用属性[instanceOfClass recentHistory](或instanceOfClass.recentHistory)将检查ivar以查看是否需要加载数据或只返回已经加载的数据。

以这种方式声明所有属性真是太过分了。

希望有所帮助。

答案 2 :(得分:1)

只是想将我的想法添加到上述所有答案中。

在我的情况下,我主要是为了让我的班级免受意外伤害。

在我的.h文件中,我只声明没有ivars的属性。在.m文件中,我使用上面的@synthesize模式来隐藏用户(包括我自己)的实际ivar,以强制使用合成/动态访问器,而不是直接使用其他ivars。你可以使用任何东西作为你的ivar名字,而不仅仅是强调它。例如你可以这样做:

@synthesize foo = _mySecretFoo;
@synthesize bar = oneUglyVarBecauseIHateMyBoss;
通过这种方式,你的老板只会看到吧,你会发现使用条形码访问器更方便,更安全 - 无论你使用点符号还是消息。

我更喜欢这种方法,

@property (getter=foo, setter=setFoo, ...) _mySecretFoo;
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss;

因为这不会强制执行私有实现和封装,而且当Xcode可以为您执行相同操作时,它只是额外的输入。有一点要记住,属性与ivars不一样!你可以拥有比ivars更多的属性,或者相反。

答案 3 :(得分:0)

保持ivar(实例变量)安全是一种惯例,因此您只能通过getter和setter访问它。