Category

187 阅读3分钟

1.Category的实现原理? 分类中的所有方法最终都会在运行时将方法合并到类对象的方法列表中 Category的底层结构是Category_t的结构体,里面存放着对象方法,类方法,协议等等信息 在运行时,runtime在read_image时候会在attachCategories中,里面会进行扩容,有一个挪动(memove)的操作,将原来的方法列表挪动到后面,所以分类中有与类中同名的方法,会覆盖类中的方法,并非真正的覆盖,而是分类的方法被放在了前面,找的时候找到方法就直接调用,不会调用后面的方法了,如果有多个分类都有同名的方法,具体调用哪个分类的方法,取决于分类编译的顺序

2.Category和Extension的区别? 前者是运行时决议,在运行时合并到类信息中 扩展是编译期决定,已经包含在类信息中

3.Category中有load方法吗?load方法什么时候调用?load方法能继承吗? -分类中有load方法 -load方法在runtime加载类、分类的时候调用,并且每个类,分类的+load方法在程序运行过程中只会调用一次,先调用类的+load方法,再调用分类的+load方法,按照编译的顺序进行调用 小结: 先调用类的+load 按照编译先后顺序调用(先编译,先调用) 调用子类的+load之前会先调用父类的+load

再调用分类的+load 按照编译先后顺序调用(先编译,先调用)

-load方法可以继承,但是一般情况下不会主动去调用load方法,都是让系统自动调用

load方法的调用原理?

prepare_load_methods schedule_class_load 先加父类的load方法,再加自己的load方法 add_class_to_loadable_list add_category_to_loadable_list

call_load_methods call_class_loads 先调用类的load方法 call_category_loads 源码中是直接找到类的load方法直接进行调用,不存在顺序的说法,而test方法是通过消息机制查找objc_msgSend查找 然后在通过call_category_loads调用分类的load方法

4.load,initialize方法的区别?在Category中的调用顺序?以及出现继承时他们之间的调用过程? == 调用时刻 1> +load方法是load_image运行时加载类和分类的时候调用 2> initialize会在类第一次接收到消息的时调用 == 调用方式 1> load是根据函数地址直接调用 2> initialize是通过objc_msgSend调用

initialize调用顺序: 先调用父类的+initialize,再调用子类的+initialize (在lookupIMPorForward查找消息时,如果自己自己类没有初始化,就会先初始化自己,在里面判断如果父类没有初始化,先初始化父类,调用父类的+initialize,总之先初始化父类,再初始化子类,每个类只会初始化1次) 小结: +initialize和+load的很大区别是,+initialize是通过objc_msgSend进行调用的,所以有以下特点 如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次) 如果分类实现了+initialize,就覆盖类本身的+initialize调用

+initialize调用过程 objc4源码解读过程 objc-msg-arm64.s objc_msgSend

objc-runtime-new.mm class_getInstanceMethod lookUpImpOrNil lookUpImpOrForward _class_initialize callInitialize objc_msgSend(cls, SEL_initialize)

5.Category能否添加成员变量?如果可以,如何给Category添加成员变量? 正常情况下在分类里添加属性,系统之后生成setter和getter的方法声明,不会生成实现 用关联对象进行间接实现 关联对象提供了以下API 添加关联对象 void objc_setAssociatedObject(id object, const void * key,id value, objc_AssociationPolicy policy)

获得关联对象 id objc_getAssociatedObject(id object, const void * key)

移除所有的关联对象 void objc_removeAssociatedObjects(id object)

关联对象原理? 实现关联对象技术的核心对象有 AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation
注意:设置关联对象为nil,就相当于是移除关联对象