Objective-C中的ivars和属性有什么区别

问题描述 投票:80回答:2

在Objective-C中使用ivars和属性的这三种方式之间的语义差异是什么?

1.

@class MyOtherObject; 
@interface MyObject {
}
@property (nonatomic, retain) MyOtherObject *otherObj;

2.

#import "MyOtherObject.h"
@interface MyObject {
    MyOtherObject *otherObj;
}
@property (nonatomic, retain) MyOtherObject *otherObj;

3.

#import "MyOtherObject.h"
@interface MyObject {
    MyOtherObject *otherObj;
}
objective-c properties instance-variables
2个回答
56
投票

数字1与其他两个不同,前向声明MyOtherObject类以最小化编译器和链接器看到的代码量,并且还可能避免循环引用。如果这样做,请记住将#import放入.m文件中。

通过声明@property(并在.m中匹配@synthesize)文件,您可以自动生成访问器方法,并按照您指定的方式处理内存语义。大多数对象的经验法则是Retain,但NSStrings例如应该使用Copy。单身人士和代表通常应该使用Assign。手写访问器繁琐且容易出错,因此可以节省大量的输入和愚蠢的错误。

此外,声明合成属性允许您使用点符号调用访问器方法,如下所示:

self.otherObj = someOtherNewObject; // set it  
MyOtherObject *thingee = self.otherObj; // get it 

而不是正常的消息传递方式:

[self setOtherObject:someOtherNewObject]; // set it
MyOtherObject *thingee = [self otherObj]; // get it 

在幕后,你真的在​​调用一个看起来像这样的方法:

- (void) setOtherObj:(MyOtherObject *)anOtherObject {

    if (otherObject == anOtherObject) {
        return;  
    }

    MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second
    otherObject = [anOtherObject retain]; // put the new value in  
    [oldOtherObject release]; // let go of the old object
} // set it

…或这个

- (MyOtherObject *) otherObject {  
    return otherObject;
} // get it

对接总疼痛,对。现在为班上的每一个ivar做这个。如果你不完全正确,就会出现内存泄漏。最好让编译器完成工作。

我看到1号没有ivar。假设这不是拼写错误,那很好,因为@property / @synthesize指令也会在幕后为你声明一个ivar。我相信这对Mac OS X来说是新的 - Snow Leopard和iOS4。

3号没有生成那些访问器,所以你必须自己编写它们。如果你希望你的访问器方法有副作用,你可以进行标准的内存管理跳舞,如上所示,然后在访问器方法中做你需要的任何工作。如果您合成属性以及编写自己的属性,那么您的版本具有优先权。

我是否涵盖了一切?


16
投票

在过去,你有ivars,如果你想让其他类设置或阅读它们,那么你必须定义一个getter(即-(NSString *)foo)和setter(即-(void)setFoo:(NSString *)aFoo;))。

什么属性给你的是免费的setter和getter(几乎!)以及ivar。因此,当您现在定义属性时,您可以设置原子性(例如,您是否允许来自多个线程的多个设置操作),以及分配/保留/复制语义(也就是说,如果setter复制新值或者只保存当前值 - 如果另一个类试图用可变字符串设置你的字符串属性很重要,以后可能会改变它。

这就是@synthesize所做的。很多人都把ivar的名字保持不变,但你可以在编写你的合成语句时改变它(即,@synthesize foo=_foo;意味着为属性_foo制作一个名为foo的ivar,所以如果你想读或写这个属性而你不使用self.foo,你将不得不使用_foo = ... - 它只是帮助你直接引用ivar,如果你只想通过setter和getter)。

从Xcode 4.6开始,您不需要使用@synthesize语句 - 编译器将自动执行此操作,默认情况下将使用_添加ivar的名称。

© www.soinside.com 2019 - 2024. All rights reserved.