我试图了解具有属性名称覆盖的synthesize
指令的用途。假设我有一个接口定义如下:
@interface Dummy ... {
UILabel *_dummyLabel;
}
@property (retain, nonatomic) UILabel *dummyLabel;
在实施文件中,我有:
@synthesize dummyLabel = _dummyLabel;
据我所知,“dummyLabel”只是实例变量“_dummyLabel”的别名。 self._dummyLabel和self.dummyLabel之间有什么区别吗?
答案 0 :(得分:24)
是。 self._dummyLabel
未定义,但_dummyLabel
不是。
Dot语法扩展为简单的方法调用,因此它不是特定于属性的。如果您有一个名为-(id)someObject
的方法,例如object.someObject
,则就像您编写[object someObject];
一样。
self.dummyLabel //works
self._dummyLabel //does not work
dummyLabel //does not work
_dummyLabel //works
[self dummyLabel]; //works
[self _dummyLabel]; //does not work
答案 1 :(得分:17)
您的理解不正确。 dummyLabel
是属性的名称,不是实例变量的别名 - 实例变量仅名为_dummyLabel
。因此,以下适用于名为Dummy
的{{1}}实例:
myObject
正常工作[myObject dummyLabel]
正常工作myObject.dummyLabel
失败[myObject _dummyLabel]
失败myObject._dummyLabel
失败myObject->dummyLabel
取决于ivar的可见性(myObject->_dummyLabel
,@public
,@private
)@protected
正常工作[myObject valueForKey: @"dummyLabel"]
取决于[myObject valueForKey: @"_dummyLabel"]
的实施(即,它将在默认情况下+accessInstanceVariablesDirectly
返回+accessInstanceVariablesDirectly
)。答案 2 :(得分:13)
拥有另一个名字的优势 对于伊娃而言,比财产是 你可以在代码中轻松看到 当你访问一个或 其他 - 安德烈·K
我无法找到“评论”按钮,因此我不得不将其作为“回答”发布。
只是想扩展Andre的评论 - 通过知道你何时使用合成属性vs vanilla变量,你知道(特别是在setter的情况下)当一个变量被保留/复制/释放时,由于你的好setter ,vs被手工操纵。
当然,如果你做得对,你可能不需要setter的帮助来正确保留/释放对象!但是也可能有其他情况引用您的ivars,self.ivar
而不是_ivar
可能会有所帮助,例如当您使用自定义setter / getter而不是默认的合成者时。也许每次修改属性时,您还希望将其存储到NSUserDefaults。所以你可能会有这样的代码:
@interface SOUserSettings : NSObject {
BOOL _autoLoginOn;
}
@property (nonatomic, assign) BOOL autoLoginOn;
@end
@implementation SOUserSettings
@synthesize autoLoginOn = _autoLoginOn;
- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {
_autoLoginOn = newAutoLoginOnValue;
[[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"];
}
@end
注意:这只是说明性代码,可能有一千个问题!
现在,在您的代码中,如果您有一行显示_autoLoginOn = YES
- 您知道它不会保存到NSUserDefaults,而如果您使用self.autoLoginOn = YES
,您确切知道会发生什么
_autoLoginOn
和self.autoLoginOn
之间的差异不仅仅是语义上的。
答案 3 :(得分:0)
我没有看到任何大的优势 将_dummyLabel重命名为dummyLabel
在某些ObjC运行时中,您很难让实例变量对类的用户不可见。对于他们在您的实例变量上添加一些前缀(或后缀)可以使您明确(或更清楚)您不希望任何人弄乱您的变量。但是你不希望你的公共功能上有那些垃圾。这可以让你把它取下来。
如果您需要使用一组新名称(setLastname与setSurname)同时维护一个带有一组名称的旧接口,这也很有用。
答案 4 :(得分:0)
旧帖子,但我认为重要的是,建议通过getter和setter访问变量(因此,使用点表示法)。强制建议仅在初始化时直接访问字段(_ivar)。
最后一段:
您应该始终直接从内部访问实例变量 一个初始化方法,因为在设置属性时, 对象的其余部分可能尚未完全初始化。即使你 不提供自定义访问器方法或知道任何副作用 在你自己的类中,未来的子类可能会很好地覆盖 行为。