目标C:区分iVars和访问器

时间:2013-04-15 08:55:10

标签: objective-c properties

 @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是一个坏主意。

2 个答案:

答案 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