实例变量和方法如何存储在Objective-C 2.0对象中?

时间:2012-08-07 00:02:37

标签: objective-c objective-c-runtime

在Objective-C的旧版本中,objc_class结构实现如下:

struct objc_class {
    Class isa;
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};

因此,表示对象的结构存储指向对象类的指针,指向对象超类的指针,对象的类名,对象的版本,信息和实例大小,对象的实例变量列表,对象的方法列表,对象的缓存和对象的协议列表。在表示对象的结构中存在这些字段是非常容易理解的,因为它们中的每一个都存储有关该对象的信息。

然而,相同的struct objc_class的Objective-C 2.0实现是这样的:

struct objc_class {
    Class isa;
};

因此,在这个版本的objc_class中,struct中只有一个字段:指向对象类结构的指针。

我的问题是,关于对象的其他信息是如何存储在Objective-C 2.0中的,因为结构中只有一个表示对象的字段?

1 个答案:

答案 0 :(得分:7)

这一切都在新的(好的,不再那么新的)非脆弱的ABI。

基本上,不是像过去那样将iVar存储在结构体内(如果超类改变了它的iVar布局,它会破坏继承),编译器会将iVar重定向放入另一层,类似于运行时的objc_setAssociatedObject

这允许一些有趣的场景。请考虑以下事项:

@interface A { // part of libA.a
   id var1;
   int var2;
   float var3;
} 

@end

@interface B : A { // part of libB.a
   id var4;
}

@end

现在,如果有一段时间,我们需要更改课程A,我们确定我们需要var3更精确(例如将其转换为long double )?

在较旧的,脆弱的ABI中,我们会被搞砸,直到libB的制造者更新。然而,有了这个新的,非脆弱的ABI,我们可以灵活地改变所有这些,而libB仍然有用。

虽然理论上这可能会在几个周期内变慢,但它增加了在运行时查找iVars的更简单方法,更灵活的子类化以及对不同类型的iVars的支持(例如__weak)。