可能重复:
Property Declaration and Automatic Backing Storage Allocation
我真的很担心这件事。
之间有区别吗?
@interface MyClass : NSObject {
}
@property(nonatomic, retain) Foo* foo;
@end
和
@interface MyClass : NSObject {
Foo* foo;
}
@property(nonatomic, retain) Foo* foo;
@end
我很乐意得到一个低级别的解释。谢谢!
答案 0 :(得分:3)
这两者之间的区别在于,第二个包含一个名为foo
的ivar,而第一个则没有。
如果您的实现包含@synthesize foo;
并且您使用的是足够现代的编译器,则对于第一种情况,编译器将自动为您添加适当的ivar。您甚至可以在同一个实现文件中访问此隐式ivar,就像在第二种情况下声明它一样。
通过现代Objective-C的另一个特性,这个ivar综合成为可能:解决脆弱的基类问题。在大多数编译语言中,ivar作为“对象地址+ ivar偏移”被访问;子类的ivars必然位于基类的ivars之后,因此子类必须知道基类的大小才能知道它自己的ivars的起始位置。因此,更改基类的大小(例如,通过添加或删除ivars)需要重新编译所有子类。 Objective-C通过在类元数据中存储类的ivar区域的大小并在运行时加载它来解决这个问题,而ivar访问则是“对象地址+基类大小+ ivar偏移”。
关于ivar合成如何工作的非常低级的细节取决于编译器,但它归结为编译器安排类的ivar区域足够大以包含合成的ivars的空间。
答案 1 :(得分:2)
简短而简单的答案:如果您没有明确定义ivars来支持您的属性,编译器将自动为您的综合属性生成后备存储。
使用此属性,您只能使用属性访问该值(通常是一件好事):
@interface MyClass : NSObject {
}
@property(nonatomic, retain) Foo* foo;
@end
self.foo = aFoo; // works
foo = aFoo; // Nope
self->foo; // Nope
有了这个,您可以使用属性访问值,并直接使用ivar访问(通常是直接进入ivar的坏事);
@interface MyClass : NSObject {
Foo* foo;
}
@property(nonatomic, retain) Foo* foo;
@end
self.foo = aFoo; // works
foo = aFoo; // yup
self->foo; // yes