用Clang编译我的.m文件【clang -rewrite-objc MyObject.m】会生成.cpp文件
编译器把我的对象MyObject转成了下面的结构体
MyObject_IMPL
struct MyObject_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSInteger *_i;
NSString * _Nonnull _ogTxt;
NSString * _Nonnull _exTxt;
};
NSObject_IMPL
struct NSObject_IMPL {
Class isa;
};
isa 是 Class类型, Class是objc_class类型的指针
// Class 是objc_class类型指针
typedef struct objc_class *Class;
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
// objc_class 继承 objc_object
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
...
};
extension看起来很像一个匿名的category,但是extension和有名字的category几乎完全是两个东西。 extension在编译期决议,它就是类的一部分,在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。extension一般用来隐藏类的私有信息,你必须有一个类的源码才能为一个类添加extension,所以你无法为系统的类比如NSString添加extension。
但是category则完全不一样,它是在运行期决议的。
就category和extension的区别来看,我们可以推导出一个明显的事实,extension可以添加实例变量,而category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。
为什么说是灾难性的?考虑下已经存在于内存中的这类对象该怎么处理?
那objc_setAssociatedObject又是如何实现的呢?下一篇寻求答案