iOS 分类Category

iOS 分类Category,第1张

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的数据,合并到类信息中(类对象、元类对象中)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/994020.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存