@interface RandomObject : NSObject
{
NSString* someObject; // I know I don't have to explicitly declare. Just to clarify my point.
}
@property (nonatomic, strong) NSString *someObject;
@end
@implementation RandomObject
@synthesize someObject;
@end
鉴于上面的代码并使用Xcode 4.3(因此,没有自动合成),这是我的问题。
属性/ synthesize将为someObject创建访问器,即getter和setter。因此,如果我想为someObject赋值,我可以这样做。
self.someObject = @"Tomato"; // [self setSomeObject: @"Tomato"];
如果我的理解是正确的,self会将@“Tomato”发送到setSomeObject方法。但是如果你这样做呢?
someObject = @"Tomato"; // or maybe _someObject = @"Tomato" if you are doing auto-synthesizing
直接访问iVar对象似乎是一个坏主意,但由于someObject是一个私有变量,所以在同一个类中你可以访问它,对吧?
我理解为什么你需要使用self.someOject,如果你想从另一个类操作someObject。但是,即使你仍然在同一个班级,为什么你需要做同样的事情。为什么直接访问iVar是一个坏主意。
答案 0 :(得分:3)
一般来说,访问者有更多的优点而不是缺点,我尽可能地使用它们。
主要问题是,您直接引用ivar的每个地方都是您的代码需要更改的另一个潜在位置。
例如,假设您在整个班级的多个地方引用了someObject
。然后需求发生变化,现在您决定在分配someObject
的值时需要进行其他一些工作。由于您已经在整个班级中直接访问了ivar,因此您现在必须在指定someObject
或重构的任何位置复制此新代码。如果您使用的是访问者,则只需要一段代码即可进行更改
- (void)setSomeObject:(id)anObject
{
if (anObject != someObject) {
someObject = anObject;
[self doSomeWork];
}
}
你可以在getter中遇到同样的问题 - 假设你在someObjects
中存储了一个对象数组 - 这很好用,但是后来你确定你实际上不需要存储{{1}因为它可以从其他值动态计算。如果您已经到处直接访问了ivar,那么这将成为一件大事。如果你坚持在吸气剂后面抽象someObjects
那么你现在要做的就是
someObject
这正是非ARC代码的想法,它将ivar的内存管理放在一个位置(在访问器后面),这样您就不必使用重复代码来丢弃代码。
答案 1 :(得分:2)
该属性不只是将对象分配给ivar。
如果您不使用ARC,该属性将自动生成保留/释放代码以处理内存管理。只是调用someObject = @"Tomato"
会产生内存泄漏(如果指定了someObject)
如果您的属性为atomic
,则该属性将提供线程安全性,而访问ivar将不是线程安全的。
有关自动生成的属性代码的示例,请参阅https://stackoverflow.com/a/589348/1597531。