"property is backed by an ivar" ?这在技术上意味着什么?



所以。。。我对目标C还相当陌生。。。带一些iTunes U胸脯。。。做一些运动和所有。。。

但是当您使用来执行@synthesis myProperty=_myIvarPropertyNameToUse。。。iOS 5将创建一个ivar来"支持"该属性。

就记忆中的事物而言,这里到底发生了什么。。。

(1) ivar是真变量吗。。。或者它是指向对象中属性位置的指针?

(2) 属性在堆上(作为对象的一部分),对吗?ivar也在堆上吗?

我想我可能正在失去大局。。。拥有一个由ivar支持的房产有什么意义?

谢谢,

Objective-C对象只是在堆上分配的C结构(好吧,或多或少)。当您声明一个实例变量(ivar)时,它被定义为该结构的偏移量。因此,如果你手动声明了一些类似的ivar(不要再这样做了,但它说明了这一点):

@interface Foo : NSObject {
NSString *ivar1;
NSString *ivar2;
}

然后,当您+alloc一个新实例(称之为foo)时,结构将是一些标头,后面跟着NSObject的ivar,后面跟着ivar1的内存,然后是ivar2的内存。CCD_ 5将是CCD_ 6点加上一些偏移。(这已经不完全是真的了,但请记住;理解旧的实现更简单。)

由于foo是一个指向结构的指针,因此您实际上可以将此偏移指针直接引用为foo->ivar1。它确实是一个结构体。千万不要这样做,但这是合法的语法。

@implementation块内部,ivar1被自动转换为self->ivar1。不要太担心self是如何实现的,但要相信它是指向结构的指针。同样,永远不要使用此->语法。这是一个底层的实现细节(现在已经不可能了;请参阅下文)。

好吧,这就是ivar。在过去(ObjC 1.0),这实际上是我们的全部。您声明了ivar,然后手工创建了访问器方法,这些方法将设置并返回它们的值。

然后ObjC2出现了,在某些情况下,它也给了我们一种叫做非脆弱ABI的东西。这在一定程度上改变了ivars的底层实现,因此您不能再实际使用->了。但你不应该一直用它。即便如此,假装事情是旧的方式更简单。更重要的是,ObjC2添加了一个名为"属性"的新东西。属性只是实现某些方法的承诺。所以当你说:

@property (nonatomic, readwrite, strong) NSString *property;

这几乎与下面的说法相同:

- (NSString *)property;
- (void)setProperty:(NSString *)aProperty;

(区别很少很重要。)请注意,这并不能提供实现。它不会产生ivar。它只是声明了一些方法。

现在在ObjC1中,我们一遍又一遍地编写相同的访问器代码。您有20个可写ivar,您编写了40个访问器方法。他们几乎一模一样。有很多机会搞砸。还有很多乏味。谢天谢地,Accessorizer。

使用ObjC2,如果添加@synthesize,编译器将免费为您提供最常见的实现。它会自动生成一个与属性同名的ivar,并编写一个getter和(如果需要的话)setter来读取和写入该ivar。传递=_property只会更改所使用的ivar的名称。我们称之为"后备ivar">

现在,在最新版本的编译器中,您甚至不需要@synthesize。这种模式非常常见,几十年来一直如此,除非你告诉编译器不要这样做,否则它现在是默认模式。它会自动合成带有前导下划线的ivar(这是最佳实践)。

您应该知道的另一条信息是,您应该始终使用访问器来访问ivar,即使是在对象内部。唯一的例外是initdealloc方法。在那里,您应该直接访问ivar(使用前导下划线)。

需要明确的是,当您执行@synthesize myProperty = _myIvarPropertyNameToUse;时,您唯一更改的是备份ivar的名称。@synthesize myProperty;行也将创建一个后备ivar,但它将被称为myProperty,而不是_myIvarPropertyNameToUse。。。

备份ivar是对象的一部分,所以是的,它在堆上。它可以用作真正的变量,这意味着您可以在目标代码中获取并设置它。

相关内容