一:概念分析
1.分类和类公用一个类对象结构;
2.分类的类方法存储到元类里面;
3.分类的方法、协议、属性在运行时(runtime)合并到类对象中。
二、编译期:
分类生成的内存结构:
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;//属性列表
};
实际例子如下:
static struct _category_t _OBJC_$_CATEGORY_lzhPerson_$_test __attribute__ ((used, section ("__DATA,__objc_const"))) =
{
"lzhPerson",
0, // &OBJC_CLASS_$_lzhPerson,
(const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_lzhPerson_$_test,
0,
(const struct _protocol_list_t *)&_OBJC_CATEGORY_PROTOCOLS_$_lzhPerson_$_test,
(const struct _prop_list_t *)&_OBJC_$_PROP_LIST_lzhPerson_$_test,
};
注:在分类编译期生成的结构中没有isa、superclass指针,以及没有ivar成员变量数组;
三、运行期:
1.通过runtime加载某个类的所有分类Category数据
2.把所有分类Category的方法、属性、协议数据合并到一个二维数组中,二维数组的每一个元素(子数组)都是一个分类的对象的数据;
后面参与编译的Category数据,会放在数组的前面(compile Soures 中的.m文件;下面先执行);
3.将合并后的分类数据(方法、属性、协议),插入到类原来数据的前面;
四、源码分析
1._objc_init 运行时的一个入口
2.map_images ->map_images_nolock()
3._read_images(hList, hCount, totalClasses, unoptimizedTotalClasses); 加载镜像 在这个里面合并分类函数
4.remethodizeClass 重新方法化;
5.remethodizeClass(cls->ISA());重新方法化元类对象
6.attachCategories(cls, cats, true flush caches); 合并方法。出入到类和分类列表;
7. 生成方法、属性、协议二维数组列表;合并完成以后的二维数组如下图:
method_list_t **mlists = (method_list_t **) 二维数组
malloc(cats->count * sizeof(*mlists));
property_list_t **proplists = (property_list_t **)
malloc(cats->count * sizeof(*proplists));
protocol_list_t **protolists = (protocol_list_t **)
malloc(cats->count * sizeof(*protolists));
mlists
[
[ method_t,method_t], 分类1
[ method_t,method_t],分类2
[ method_t,method_t],分类3
]
proplists
[
[ property_t,method_t], 分类1 属性
[ property_t,method_t],分类2属性
[ property_t,method_t],分类3属性
]
8.methods.attachLists 奖所有分类的方法、属性、协议附加到类对象的数组对象中
9. 添加到类对象中:
memmove(array()->lists + addedCount, array()->lists, 内存移动
oldCount * sizeof(array()->lists[0]));
memcpy(array()->lists, addedLists,
addedCount * sizeof(array()->lists[0])); 内存拷贝
五、分类Category和扩展的extension的区别是:
1.类扩展(extension)是category的一个特例,有时候也被称为匿名分类或者私有类。他的作用是为一个类添加一些私有的成员变量和方法。
2.类扩展能写点啥?和分类不同,类扩展即可以声明成员变量又可以声明方法。
3.类扩展听上去很复杂,但其实我们很早就认识他了。你记得继承自UIViewController的ViewController和继承自NSObject的类有什么不同么?
4.类扩展可以定义在.m文件中,这种扩展方式中定义的变量都是私有的,也可以定义在.h文件中,这样定义的代码就是共有的,类扩展在.m文件中声明私有方法是非常好的方式。
5.类扩展中添加的新方法,一定要实现。categorygory中没有这种限制。
网友评论