Objective-C声明属性创建定义的ivar?

时间:2011-07-27 14:26:54

标签: objective-c

  

可能重复:
  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

我很乐意得到一个低级别的解释。谢谢!

2 个答案:

答案 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