一、Category简介
category是Objective-C 2.0之后添加的运行时特性,主要的作用就是为已经存在的类添加方法。它可以让类的实现分布在几个不同的文件里,有如下优点
一是减少单个文件的大小,
二是可以把不同的功能分别放在不同的category里,
三,方便多个开发者维护,
四,可以按需求加载不同的category.
五,声明私有方法
注意:category只可以给类添加方法或属性(只有setter和getter方法,没有变量),但是添加不了变量(ivar)
二、Category和Extension的区别
extension和category看起来和使用起来很像,但是extension和category完全是两个东西。extension在编译期处理,它本身就是类的一部分,在编译的时候,和头文件里的@interface以及实现文件里的@implemention一起形成一个完整的类,它跟类一起加载,一起释放,所以extension可以添加变量。而category是运行时行为。Extension一般用来隐藏类的私有信息,必须知道类的源码可以为类添加extention,而category则不用.
三、Category结构
所有的oc类和对象,在runtime层都是一个结构体,category也一样,在runtime时,category也是一个结构体category_t,它的结构如下所示:
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;
method_list_t *methodsForMeta(bool isMeta) {
if (isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta) {
if (isMeta) return nil; // classProperties;
else return instanceProperties;
}
};
结构体里包含了类、类的名字、实例方法列表、类方法列表、协议列表、属性等
四、Category实现原理
插件不灵了。。新代码块插件比较麻烦,下面就不贴源码了,感兴趣的同学可以自己翻下源码
1.运行时,把category的实例方法、协议及属性添加到类上
2.运行时,把catetgory的类方法和协议添加到类的metaclass上(元类)
3.category添加方法列表的时候,先获取类的消息列表,然后依次追加
4.方法调用时(即消息响应时),获取实例的方法列表,倒序查找方法,然后响应
5.类方法同上
五、几个注意点
Category可以添加方法、属性,但是不可以添加变量,添加属性也是只有setter跟getter,原因是:oc里用于给类添加变量的方法lass_addIvar(),只有在构建一个类的过程中才可以调用,一旦完成类的定义,就不能调用添加变量了,当然apple也尝试过可以添加变量,但是没有实施,源码里有类似的代码,但是被注释掉了。
category的方法被加到类或实例中的时候,是加在方法列表的后面的,但是响应的时候,是从方法列表里倒序查找的,所以,后加载的方法会先响应,如果category中的方法跟类中重复,会响应category中的方法,如果两个category都有此方法,那么后加载的会响应,当然,可以通过获取方法列表,正序取出方法来完成响应。
同理,多个.a里如果有相同类的category中方法重名,跟第2条同理
欢迎大家提出宝贵意见