Objective-C / ARC ivar vs property

时间:2015-01-20 00:48:00

标签: objective-c

如果不是对伊塔尔和财产的彻底辩论,我一直在Google和堆栈中上下阅读许多文章。但是,即使在所有这些阅读之后,我仍然感到困惑。

我理解ivar是私有的,属性通常用于公开(井)类属性。但我理解属性不止于此,它们包含Getters和Setter,当涉及内存管理时(即使在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

4 个答案:

答案 0 :(得分:1)

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

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

大多数人都将ivar名称与属性名称相同,但在编写@synthesize语句时可以使其成为其他名称(即@synthesize foo = _foo;意味着为该属性创建一个名为_foo的ivar富)。

请注意,从Xcode 4.6开始,您不需要使用@synthesize语句 - 默认情况下,编译器会使用_前缀ivar的名称。所以Apple不再推荐@synthesize用于新代码。

答案 1 :(得分:0)

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

如果您改为编写自己的方法-(void)setMyArray;,它可能会执行不同的操作,但是如果不自行声明,您也不会获得私有的ivar _myArray

答案 2 :(得分:0)

self.myArray = [NSMutableArray array];init中被视为不良格式。您应该避免在初始化时完全使用setter。风险在于子类可能会覆盖该方法,在这种情况下,您在一个尚未init编辑的类上调用方法(因为它只能到目前为止)作为init你)。请参阅obligatory Mike Ash citation

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

ARC正确地进行内存管理,但没有问题。辩论完全是您在技术上要展示的内容以及您希望内部代码具有的适应性。我倾向于选择显式的实例变量,因为这会引发私人实施细节'。

答案 3 :(得分:0)

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

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

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