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

标签 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;
};

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

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

struct objc_class {
    Class isa;
};

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

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

最佳答案

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

基本上,编译器不是像以前那样将 iVar 存储在结构中(如果父类(super class)更改它的 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 仍然有效。

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

关于objective-c - 实例变量和方法如何存储在 Objective-C 2.0 对象中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11837589/

相关文章:

ios - 将 IMP 转换为 Swift 中的函数

ios - 在 Objective-C 中将自定义类注入(inject)子类继承树

ios - 遍历 nsmutablearray 并删除重复的对象

ios - 标签栏的底部未正确着色

ios - 为什么在 SDWebImage "strong reference to UIImageView might cause a crash in the nested block"中?

objective-c - class_addIvar 的对齐在 Objective-C 中有什么作用?

objective-c - 我的 isa-swizzling 破坏了 KVO

ios - 使用 object_setIvar 时的 EXC_BAD_ACCESS

ios - MFMailComposeViewController 对象未在 iPad 中分配,但在模拟器中工作正常

objective-c - NSPopover 颜色