OC为什么 Category不能添加属性

用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又是如何实现的呢?下一篇寻求答案

你可能感兴趣的:(OC为什么 Category不能添加属性)