Category的底层原理

category是Objective-C 2.0之后添加的语言特性,为本类扩展私有方法,
分类的基础知识可以看这篇category基础知识篇

1、category中能添加属性吗?
struct _category_t {
         const char *name;    //类名
         struct _class_t *cls;  /类
         const struct _method_list_t *instance_methods; //实例方法列表
         const struct _method_list_t *class_methods;    //类方法列表
         const struct _protocol_list_t *protocols;      //协议列表
         const struct _prop_list_t *properties;         //属性列表
         };

category中也可以添加属性,只不过@property只会生成setter和getter的声明,不会生成setter和getter的实现以及成员变量,点语法是可以写,只不过在运行时调用到这个方法时候会报方法找不到的错误。

2、为什么category不能添加成员变量

Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。它的定义如下:

typedef struct objc_class *Class;

objc_class结构体的定义如下:

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
    Class super_class                              // 父类
    const char *name                               // 类名
    long version                                  // 类的版本信息,默认为0
    long info                                     // 类信息,供运行期使用的一些位标识
    long instance_size                            // 该类的实例变量大小
    struct objc_ivar_list *ivars                  // 该类的成员变量链表
    struct objc_method_list **methodLists        // 方法定义的链表
    struct objc_cache *cache                     // 方法缓存
    struct objc_protocol_list *protocols         // 协议链表
#endif
};

objc_method_list指针的指针。在Runtime中,objc_class结构体大小是固定的,不可能往这个结构体中添加数据,只能修改。所以ivars指向的是一个固定区域,只能修改成员变量值,不能增加成员变量个数。methodList是一个二维数组,所以可以修改*methodLists的值来增加成员方法,虽没办法扩展methodLists指向的内存区域,却可以改变这个内存区域的值(存储的是指针)。因此,可以动态添加方法,不能添加成员变量。

3、Category的实现原理或者本质 ?

  • Category编译之后的底层结构是struct category_t,里面存储着分类的对象方法、类方法、属性、协议信息
  • 在程序运行的时候,runtime会将Category的数据,合并到类信息中(类对象、元类对象中)

4、Category(分类)和Extension(扩展)的区别是什么?

  • Extension在编译的时候,它的数据就已经包含在类信息中
  • Category是在运行时,才会将数据合并到类信息中
  • Extension可以添加实例变量,而Category不可以。
  • Extension和Category都可以添加属性,但是Category的属性不能生成成员变量和getter、setter方法的实现。

5、load方法是什么时候调用的?load 方法能继承吗?

  • load方法在runtime加载类、分类的时候调用
  • load方法可以继承,但一般情况下不会主动去调用load方法,都是让系统自己调用

6、Category的加载处理过程是什么?

  • 通过Runtime加载某个类的所有Category数据
  • 把所有Category的方法、属性、协议数据,合并到一个大数组中,
    后面参与编译的Category数据,会在数组的前面
  • 将合并后的分类数据(方法、属性、协议),插入到类原来数据的前面

7、Category的+load方法调用顺序是什么?

  • +load方法会在runtime加载类、分类时调用
  • 每个类、分类的+load,在程序运行过程中只调用一次
  • 先调用类的+load
    1、按照编译先后顺序调用(先编译,先调用)
    2、调用子类的+load之前会先调用父类的+load
  • 再调用分类的+load
    1、按照编译先后顺序调用(先编译,先调用)

8、

你可能感兴趣的:(Category的底层原理)