OC分类Category

分类Category

1.分类的应用:
  • 声明私有方法
  • 分解体积庞大的类文件
  • 把Framework的私有方法公开
2.分类的特点(或者说分类跟扩展的区别):
  • 运行时决议:在编写完分类文件后,并没有直接把分类内容添加到相关的宿主类上。而是在运行时使用runtime把分类的内容添加到宿主类上。
  • 可以为系统类添加分类
3.分类的优、缺点:

优点:

  • 不需要通过增加子类而增加现有类的行为(方法),且类目中的方法与原始类方法基本没有区别;

  • 通过类目可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性;

缺点:

  • 无法向类目添加实例变量,如果需要添加实例变量,只能通过定义子类的方式;

  • 类目中的方法与原始类以及父类方法相比具有更高优先级,如果覆盖父类的方法,可能导致super消息的断裂。因此,最好不要覆盖原始类中的方法。

4.分类加载流程:

在运行APP的时候,加载完动态链接库,会加载可执行文件,通过runtime生成类、成员变量、方法列表,在宿主类的方法列表生成完之后,会开始加载分类的方法列表。

取到所有分类的列表数组(按编译时的顺序排序),然后按倒序从分类列表里取出每个分类的方法列表,生成一个二维数组。

把二维数组中的方法,按正序即从0索引开始,放入到宿主类的方法列表中(一维的数组)。
所以分类才拥有了“覆盖”原有类的方法功能,其实是原方法是存在的,只是分类的方法列表加入到了原有类的方法数组的前边,获得优先执行权。

5.分类中都可以添加哪些内容:
struct category_t {
    const char *name;                           分类名称
    classref_t cls;                             该分类所属的宿主类
    struct method_list_t *instanceMethods;      实例方法列表
    struct method_list_t *classMethods;         类方法列表
    struct protocol_list_t *protocols;          协议列表
    struct property_list_t *instanceProperties; 实例属性列表
    
    ... 省略
}

在编译时候,分类会被编译成一个category_t的机构体,储存如下信息。

  • 增加实例方法
  • 增加类方法
  • 增加协议
  • 增加实例属性。在分类中定义了一个属性,实际上只声明了对应的get方法和set方法,并没有在分类中添加实例变量var。
  • 增加实例变量。⚠️使用 runtime关联对象 技术来添加。
6.分类添加过程:

在程序运行时候,runtime会把分类的实例方法等信息合并到类对象的实例方法列表中,会把分类的类方法合并到元类对象的类方法列表中。

以添加实例方法为例:
运行时候,会遍历分类列表,拿到每一个分类的实例方法列表

分类1的实例方法列表 array1 [method_t, method_t]
分类2的实例方法列表 array2 [method_t, method_t]

然后根据获取到的所有分类的实例方法列表数 和 原宿主类的实例方法列表,重新分配内存,数据结构为一个新的二维数组

 new_array [所有分类的实例列表数目 + 宿主类的实例列表数][]

最后把宿主类的实例列表移动都数组后面,并把所有分类的实例列表加入到新申请的二维数组的前边

[
array1,
array2.
[原宿主类的实例方法列表]
]


补充知识1

关联对象技术: 可以给分类添加成员变量。
#关联对象: 使用objc_setAssociatedObject函数可以给某个对象关联其他的对象。
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
 
#获取关联的对象: 使用objc_getAssociatedObject函数可以通过键来取出某个对象的关联对象。
id objc_getAssociatedObject(id object, const void *key)
 
#移除关联的对象:使用objc_removeAssociatedObjects函数可以移除某个对象身上的所有关联的对象。
void objc_removeAssociatedObjects(id object)
注意:

void objc_removeAssociatedObjects(id object)函数移除的是某个对象身上的所有关联的对象。
objc没有给我们提供移除object身上单个关联对象的函数,所以,我们一般通过objc_setAssociatedObject函数传入nil来达到移除某个关联对象的目的。
如下:
void objc_setAssociatedObject(object, key, nil, policy);

key:    要保证全局唯一,key与关联的对象是一一对应关系。必须全局唯一
value:  要关联的对象。
policy: 关联策略。有五种关联策略。
OBJC_ASSOCIATION_ASSIGN   等价于   @property(assign)。
OBJC_ASSOCIATION_RETAIN_NONATOMIC   等价于   @property(strong, nonatomic)。
OBJC_ASSOCIATION_COPY_NONATOMIC   等价于   @property(copy, nonatomic)。
OBJC_ASSOCIATION_RETAIN   等价于   @property(strong,atomic)。
OBJC_ASSOCIATION_COPY   等价于   @property(copy, atomic)。

问:关联对象技术给分类添加的成员变量放在了哪里?
答:关联对象由AssociationsManager管理并在AssociationsHashMap存储。
所有对象的关联内容都在同一个容器中。

问:怎样清除某一个关联对象被关联的值?
答:setAssociatedObject方法中value值设为nil即可。



补充知识2

扩展Extension

1.一般用扩展做什么:

  • 声明私有属性。
  • 声明私有方法
  • 声明私有成员变量。

2.拓展的特点(与分类区别):

  • 编译时决议
  • 只以声明的形式存在,多数情况下寄生于宿主类的.m实现文件中
  • 不能为系统类添加拓展


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342