iOS 分类Category

1.Category定义

Category的主要作用是为已经存在的类添加方法。
Objective-C 中的 Category 就是对装饰模式的一种具体实现。它的主要作用是在不改变原有类的前提下,动态地给这个类添加一些方法。

2.使用场景

  • 可以按照功能分组,放到不同的分类里,使类结构更清晰
  • 降低耦合性,同一个类可以有多个开发人员进行开发
  • 模拟多继承
  • 声明私有方法
  • 分解体积庞大的类文件
  • 把静态库的私有方法公开
  • 模拟多继承(另外可以模拟多继承的还有protocol)

3.特点

  • 1.分类是用于给原有类添加方法的,因为分类的结构体指针中,没有属性列表,只有方法列表。 原则上讲它只能添加方法, 不能添加属性(成员变量),实际上可以通过其它方式添加属性 ;
  • 2.分类中的可以写@property, 但不会生成 setter/getter方法, 也不会生成实现以及私有的成员变量,会编译通过,但是引用变量会报错;
  • 3.如果分类中有和原有类同名的方法, 会优先调用分类中的方法, 就是说会忽略原有类的方法,同名方法调用的优先级为 分类 > 本类 > 父类
  • 4.如果多个分类中都有和原有类中同名的方法, 那么调用该方法的时候执行谁由编译器决定;编译器会执行最后一个参与编译的分类中的方法。
  • 5.运行时决议
  • 6.同名分类方法生效取决于编译顺序
  • 7.名字相同的分类会引起编译报错
  • 8.运行时决议

4.原理

一个类的类对象只有一个,存储着实例方法,元类对象也只有一个,存储着类方法
实例方法的调用轨迹是实例对象通过isa指针找到类对象,在类对象的方法列表中查找该方法,如果找不到,就通过superclass指针继续向上查找
类方法的调用轨迹是类对象通过isa指针找到元类对象,在元类对象的方法列表中查找该方法,如果找不到,就通过superclass指针继续向上查找

(1)分类的实例方法是被加载到类对象中,分类的类方法也是被加载到元类对象中

(2)编译时,分类是被编译成_category_t结构体,_category_t结构体存储着分类的实例方法列表、类方法列表、协议、属性。
分类实例方法、类方法不是在编译时,加载到类对象、元类对象中

在.cpp文件中可以导出这个结论

static struct _category_t _OBJC_$_CATEGORY_Person_$_Test __attribute__ ((used, section ("__DATA,__objc_const"))) =
{
    "Person",
    0, // &OBJC_CLASS_$_Person,
    (const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_Test,
    (const struct _method_list_t *)&_OBJC_$_CATEGORY_CLASS_METHODS_Person_$_Test,
    0,
    0,
};

static struct /*_method_list_t*/ {
    unsigned int entsize;  // sizeof(struct _objc_method)
    unsigned int method_count;
    struct _objc_method method_list[1];
} _OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_Test __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_objc_method),
    1,
    {{(struct objc_selector *)"run", "v16@0:8", (void *)_I_Person_Test_run}}
};

static struct /*_method_list_t*/ {
    unsigned int entsize;  // sizeof(struct _objc_method)
    unsigned int method_count;
    struct _objc_method method_list[1];
} _OBJC_$_CATEGORY_CLASS_METHODS_Person_$_Test __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_objc_method),
    1,
    {{(struct objc_selector *)"test", "v16@0:8", (void *)_C_Person_Test_test}}
};

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

(3)分类的数据是通过runtime动态加载到类信息中(类对象、元类对象中)

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

Original: https://blog.csdn.net/zcvbnh/article/details/122367061
Author: zcvbnh
Title: iOS 分类Category

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/664461/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球