Objective-C/ARC ivar vs property



我一直在谷歌和堆栈上上下下,读过很多文章,如果不是关于ivars和属性的直接辩论。 但是,即使在阅读了所有这些之后,我仍然感到困惑。

我知道 ivar 是私有的,属性通常用于公开(井)类属性。 但是我知道属性不止于此,它们包含 Getters 和 Setters,当涉及到内存管理(即使在 ARC 下)时,我可以看到专门使用它们的好处。

但我的问题是;既然我们有ARC,这些都不再重要吗? (请参阅下面的示例代码中的注释)。

考虑:

@interface MyClass
@property(strong) NSMutableArray *myArray;
@end
@interface MyClass
-(instancetype)init {
    if (self = [super init]) {
        self.myArray = [NSMutableArray array];
        // OR
        // Will this NOT call the Setter?  Hence, leading
        // to possible memory leak issues?
        _myArray = [NSMutableArray array];
    }
    return self;
}
@end
self.myArray = [NSMutableArray array];

init中被认为是不好的形式。您应该避免在初始化中完全使用 setter。风险在于子类可能会覆盖该方法,在这种情况下,您将在尚未init的类上调用方法(因为它只能init您)。请参阅强制性的迈克·阿什引文。

_myArray = ... 不调用 setter,因此是init的正确形式,无论您是否也有属性。

ARC 使正确的内存管理几乎不存在问题。争论完全是你想要在技术上公开的内容,以及你希望你的内部代码有多大的适应性。我倾向于使用显式实例变量,因为这会大喊"私有实现细节"。

回到 Objective-C 的旧时代,你有 ivars,如果你想让其他类设置或读取它们,那么你必须定义一个 getter 和一个 setter。

正如我向您解释的那样,使用属性,您可以免费(几乎!)获得 setter 和 getter 以及一个实例变量。因此,在定义属性时,可以设置原子性以及分配/保留/复制内存管理语义。

大多数人将 ivar 名称与属性名称保留为相同,但是当您编写 @synthesize 语句时,它可以被设置为其他名称(即,@synthesize foo=_foo; 表示为属性 foo 制作一个名为 _foo 的 ivar)。

请注意,从 Xcode 4.6 开始,您不需要使用 @synthesize 语句 - 默认情况下,编译器会在 ivar 的名称前面加上 _。因此,苹果不再推荐@synthesize用于新代码。

在这两种情况下,分配的值都将被保留,因为您将其分配给强变量。(强是引用对象实例的变量的默认值)

在第一个示例中,将调用方法 -setMyArray: ,在生成的 setter 的情况下,该方法会将值存储到 _myArray。在第二种情况下,不会调用 -setMyArray:

对于给定的代码,当再次设置_myArray时,已分配给_myArray的对象将正确减少其引用计数。(将删除对该对象的现有强引用。

第一次调用将调用 setter,而第二次调用不会,但是这两个调用都将覆盖 ivar _myArray 。例如,如果您先self.myArray = @[@"Hello"];然后_myArray = @[@"World"],则打印出self.myArray_myArray将打印@[@"World"]

如果你改用自己的方法-(void)setMyArray;,它可能会做不同的事情,但是如果不自己声明,你也不会得到私有的ivar _myArray

最新更新