iOS 应用中为什么要使用下划线前缀?
@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 4之前,很容易混淆这两者。您可以执行以下操作:
self.foo = foo1;
foo = foo2;
- (NSMutableArray *)recentHistory;
{
if (_recentHistory == nil)
{
// Get it and set it, otherwise no work is needed... hooray!
}
return _recentHistory;
}
因此,对属性 [instanceOfClass recentHistory](或 instanceOfClass.recentHistory)的调用将检查 ivar 是否需要加载数据,或者只返回已经加载的数据。
这种方式声明所有属性可能有些过头了。
希望能有所帮助。
@synthesize recentHistory;
并在 recentHistory
方法内部使用实例变量 recentHistory
或 self->recentHistory
,只要确保不使用属性名称 self.recentHistory
或 [self recentHistory]
以避免递归。 - Mattias Wadman我只是想在所有上面的答案中加入我的想法。
在我的情况下,我主要使用它来保护我的类免受意外伤害。
在我的.h文件中,我仅声明属性而没有ivars。在.m文件中,我使用上述@synthesize
模式将实际的ivar隐藏起来,包括我自己在内的用户,强制使用合成/动态访问器而不是直接使用ivar。您可以为ivar名称使用任何内容,而不仅仅是下划线。例如,您可以这样做:
@synthesize foo = _mySecretFoo;
@synthesize bar = oneUglyVarBecauseIHateMyBoss;
这样,你的老板只会看到bar,而你会发现使用bar访问器更容易、更安全,无论你使用点符号还是消息。
我更喜欢这种方法。
@property (getter=foo, setter=setFoo, ...) _mySecretFoo;
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss;
因为这不强制私有实现和封装,而且只是在Xcode可以为你完成相同的工作时多余的输入。要记住一件事,属性与实例变量(ivar)并不相同!你可以拥有比实例变量更多的属性,或者反过来。
@implementation {...}
块中不显式声明ivars来完成这个操作。如果您永远不会引用oneUgly
,那么使用@synthesize bar = oneUgly;
有什么优势呢?为什么不只是使用@synthesize bar;
?这是因为如果您写例如bar = 123.0
,您的方法会出现错误吗? - Tim@synthesize age = numberOfYears;
它还允许我这样做:SomeAccount *account = [SomeAccount defaultAccount]; self.account = account;
而不用担心错误,因为这是我的代码编写风格。这纯粹是方便和编码风格。 - Salam Horani保持ivar(实例变量)安全是一种惯例,所以你只能通过getter和setter来访问它。
if( _foo != nil ) [_foo release];
编译器没有生成与 nil 的测试,这将是无用的,它更愿意测试新值是否与先前的值不同。请参见 https://dev59.com/5FHTa4cB1Zd3GeqPOxwY#3925204 了解示例。 - jv42Foo *tmp = [Foo foo]; self.foo = tmp; self.foo = tmp;
运行您的代码,以查看其崩溃。 - jv42