OC 中的 category
2018-09-17 本文已影响8人
LeeDev
在谈category的时候,就需要对比的看下扩展。
扩展
:编译的时候决定,一般来说 是声明 私有的属性和变量
类别
:主要是 在运行时
决定 。同时 可以添加类/实例方法
、 协议
、属性
。
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;
// Fields below this point are not always present on disk.
struct property_list_t *_classProperties;
method_list_t *methodsForMeta(bool isMeta) {
if (isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};
查看代码:
在objc-runtime-new.mm
中找到入口 函数 Class realizeClass(Class cls)
, 在最后有个 methodizeClass(cls)
就是加入类别的方法.内部有
// Install methods and properties that the class implements itself.
method_list_t *list = ro->baseMethods();
if (list) {
prepareMethodLists(cls, &list, 1, YES, isBundleClass(cls));
rw->methods.attachLists(&list, 1);
}
然后我们 查看 methods.attachLists 方法
void attachLists(List* const * addedLists, uint32_t addedCount) {
if (addedCount == 0) return;
if (hasArray()) {
//
// many lists -> many lists
uint32_t oldCount = array()->count;
uint32_t newCount = oldCount + addedCount;
//1.重新分配,相当于 用空间换时间
setArray((array_t *)realloc(array(), array_t::byteSize(newCount)));
array()->count = newCount;
//内存移动 memmove(void *__dst, const void *__src, size_t __len)
//2.【OldList1,OldList2,OldList3】 往后移动 addedCount 位置
// array()->lists + 1 : 是相当于 偏移 sizeOf(array()->lists[0])的位置
memmove(array()->lists + addedCount, array()->lists,
oldCount * sizeof(array()->lists[0]));
//memcpy(void *__dst, const void *__src, size_t __n)
//3.相当于 把 新的数组【CateList1,CateList2】放入到 array()->lists 的起始位置
memcpy(array()->lists, addedLists,
addedCount * sizeof(array()->lists[0]));
}
。。。。
}