访问属性方法和类字段之间的差异(Objective-C)

访问属性方法和类字段之间的差异(Objective-C),objective-c,Objective C,假设我有一段代码: @interface Foo : NSObject { Bar *bar; } @property (retain, nonatomic) Bar *bar; @end 使用此字段/属性时,行与行之间是否存在任何差异: [self.bar doStuff]; 及 ? 在执行赋值时,property方法将执行正确的保留,但如上所述,对属性的读取访问如何?有什么不同吗?合成(或正确手写)的非原子存取器在功能上等同于 - (Bar *)bar { retur

假设我有一段代码:

@interface Foo : NSObject {
    Bar *bar;
}

@property (retain, nonatomic) Bar *bar;

@end
使用此字段/属性时,行与行之间是否存在任何差异:

[self.bar doStuff];

?

在执行赋值时,property方法将执行正确的保留,但如上所述,对属性的读取访问如何?有什么不同吗?

合成(或正确手写)的非原子存取器在功能上等同于

- (Bar *)bar
{
    return bar;
}
因此,您的两个示例之间没有功能上的差异


但是,在-dealloc或您的初始值设定项之外,通过访问器一致地访问属性是一个好主意。

使用访问器self.bar将转换为方法调用:[self bar]。句点语法仅用于外观。直接访问成员变量不需要额外的函数调用,因此速度稍快。只有当您在循环中访问它,或者在某个差异累积的过程中访问它时,它才真正重要。(在iPhone上)为属性创建的setter在进行键值编码时也有一些额外的开销。当您调用“setBar:”或说“self.bar=”时,会发送KVO通知,因此反复调用会导致大量通知

不过Jim是对的——非原子@property和在代码中直接使用变量之间没有函数上的区别。除非你真的关心速度,否则使用这个属性可能是你最好的选择。

有很大的不同。
[self.bar doStuff]
相当于
[[self.bar]doStuff]

[bar doStuff]
相当于
[self->bar doStuff]

前者使用accessor方法,后者直接访问实例变量bar

如果在
属性上使用
@synthesis
指令,编译器将为您生成两种方法:

- (void)setBar:(Bar*)b;
- (Bar*)bar;

还请注意,编译器生成的setter方法将保留您在
@property
声明中告诉它的
Bar
实例

如果使用方便的Bar类构造函数为字段赋值,则Bar字段将比使用Retain选项的Bar属性更快变为僵尸,因为引用计数不会因赋值给字段而增加,有时会遇到“访问解除分配的对象”错误

然而,尽管getter和fieldselector机制之间存在差异,但上述两行之间仍然没有功能上的差异。也就是说,同一个对象将接收相同的消息,对吗?嗯,可能有。因为您可以自由地以任何方式实现方法栏。例如,您可以返回一个代理对象或任何东西。即使在合成访问器方法的情况下,它们的行为也可能有所不同,就像在将属性设置为原子时同步访问一样。但是在我合成属性的情况下,即使存在同步、保留或其他情况,上述行之间仍然没有功能上的差异,从某种意义上说,同一个对象接收相同的消息,对吗?这肯定是有区别的。派生类可以重写-(Bar*)Bar并返回另一个对象。否。考虑重写-(bar *)条的派生类;Nikolai的观点很好-由于重写的-(Bar*)Bar可能会添加额外的业务逻辑或返回除Bar以外的其他内容,因此使用该属性可能并不等同于直接引用变量。谢谢你指出这一点!需要明确的是:您谈论的开销并不取决于通过@synthesis语句创建的setter。即使您自己实现了它们,如果注册了观察员,也会发送通知。这是通过isa swizzling实现的。
- (void)setBar:(Bar*)b;
- (Bar*)bar;