4

所以......我对Objective C还是很陌生......拿一些iTunes U corses......做一些练习......

但是当你使用 @synthesize myProperty = _myIvarPropertyNameToUse; ... iOS 5 将创建一个“支持”该属性的 ivar。

就事情在记忆中的位置而言,这里到底发生了什么......

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

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

我想我可能会失去大局......拥有由 ivar 支持的财产有什么意义?

谢谢,

4

2 回答 2

14

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

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

然后,当您+alloc创建一个新实例(调用它foo)时,该结构将是一些标头,后跟 NSObject 的 ivars,然后是 memory for,ivar1然后是 memory for ivar2ivar1foo点加上一些偏移量。(这不再完全正确,但请继续关注我;理解旧的实现更简单。)

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

@implementation块内部,ivar1自动翻译为self->ivar1. 不要太担心如何self实现,但相信它是指向你的结构的指针。同样,永远不要使用这种->语法。这是一个底层的实现细节(并且不再总是可能的;见下文)。

好的,这就是 ivar。在过去(ObjC 1.0),这实际上就是我们所拥有的。您声明了您的 ivars,然后您手动创建了可以设置和返回其值的访问器方法。

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

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

这几乎等同于说以下内容:

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

(差异很少很重要。)请注意,这不提供实现。它不会创建 ivars。它只是声明了一些方法。

现在在 ObjC1 中,我们一遍又一遍地编写相同的访问器代码。你有 20 个可写的 ivars,你写了 40 个访问器方法。它们几乎完全相同。搞砸的机会很多。而且很乏味。谢天谢地Accessorizer

使用 ObjC2,如果您添加了@synthesize. 它会自动创建一个与属性同名的 ivar,并编写一个 getter 和(如果需要)setter 来读取和写入该 ivar。传递=_property只是更改使用的 ivar 的名称。我们称之为“支持 ivar”。

现在,在最新版本的编译器中,您甚至不需要@synthesize. 这种模式非常普遍,并且已经存在了几十年,现在它是默认的,除非你告诉编译器不要这样做。它会自动合成带有前导下划线的 ivar(这是最佳实践)。

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

于 2012-10-15T16:19:40.083 回答
0

需要明确的是,当您这样做时@synthesize myProperty = _myIvarPropertyNameToUse;,您唯一的更改是支持 ivar 的名称。该行@synthesize myProperty;还将创建一个支持 ivar,但它会被称为 myProperty,而不是 _myIvarPropertyNameToUse...

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

于 2012-10-15T15:56:18.140 回答