您可以想象我在.h文件中有属性:
@property (nonatomic) NSString * myText;
@property (nonatomic) SomeClass * someObj;
现在,在类实现中。
说,我没有忘记使用合成,我打电话给:
@synthesize myText, someObj;
现在在代码中说我忘记将self
放在属性名称之前(并直接引用ivar):
myText = @"Hello";
someObj = [[SomeClass alloc] init];
我的问题是:这是一个问题吗?它会导致什么问题?或者没什么大不了的?
PS。说我正在使用ARC。
答案 0 :(得分:2)
我的问题是:这是一个问题吗?
这称为“直接ivar访问”。在某些情况下,这不是问题,而是必需品。初始化器,dealloc和访问器(setter / getters)是您应该直接访问self
的ivars的地方。在几乎所有其他情况下,您都会赞成访问者。
应避免直接访问self
以外的实例的ivars。这里容易出问题的是,您可能会读取或写入无效的地址(未定义的行为),就像C结构一样。当消息对象为nil
时,不执行该消息的实现。
会导致什么问题?
最大的两个:
答案 1 :(得分:1)
为清楚起见,我建议始终使用
self.propertyname
而不是
propertyname
因为这消除了什么变量属于该类或在方法中已在本地声明的任何混淆。
要强制执行此操作,请尽量避免使用@synthesize,只有在您提供两个自定义getter 和 setter(但不是一个或另一个)时才需要
编译器自动允许你在getter / setter中使用_propertyname(这是防止函数递归调用所必需的)
答案 2 :(得分:1)
只有在您打算这样做时,才应该意外访问基础实例变量。
意外的副作用可能是KVO不起作用,不会调用覆盖访问器方法,copy
和atomic
属性也没有效果。
您不需要使用@synthesize
since Xcode 4.4,如果您使用默认综合,则编译器会执行等效的
@synthesize myText = _myText;
这样
_myText = @"Hello";
self->_myText = @"Hello";
是等效的,myText = @"Hello";
会导致“未定义的标识符”编译器错误。
如果编译器只使用@synthesize myText
(出于向后兼容性原因):
@synthesize myText = myText;
容易出错。
请注意,有valid reasons来使用底层实例变量而不是访问者 - 但是这样做的风格很糟糕。
答案 3 :(得分:0)
30年来,推荐的做法是:
.
运算符来读写ivars。您需要在以下几种情况下直接访问ivars:
除了这些情况(以及其他一些情况),请不要直接访问ivars。并在所有ivars前加下划线,以确保您不会意外访问它们并防止它们在您编码时出现在xcode的自动完成/智能感知中。
该公约的两个主要原因是:
当然,你可以做任何你想做的事。但是这个会议现在已经存在了几十年,而且很有效。没有理由不遵循它。
答案 4 :(得分:-1)
与其他答案似乎达成一致意见相反,我建议始终使用直接ivar访问,除非您非常清楚自己在做什么。
我的推理很简单:
使用ARC,使用直接属性访问并不复杂,只需指定一个 对ivar和ARC的价值在于内存管理。
(这是我的要点:)属性访问者可能有副作用 这不仅适用于您编写的属性访问器,也可能适用于 您正在实施的类的子类 现在,在子类中定义的这些访问器可能很好地依赖于子类的状态 设置在它的初始化程序中,此时尚未执行,因此您调用它们 访问器可能会导致从对象的未定义状态到应用程序的任何内容 抛出异常并崩溃。
现在,并非每个类都可以设计为子类,但我认为最好只使用一种风格,而不是根据您当前正在编写的类不一致。
旁注:我还建议在每个ivar的名称前加上_
,因为当你没有@synthesize
时,编译器会自动为你的属性做。