分类 扩展 关联对象
思路
- 做了哪些事情?
- 特点
- 局限性
- 源码分析
1. 概述:
不知道源码的情况下为类添加方法,可在现有的类的基础上添加新的方法。
2. 主要作用
- 分解体积大的类文件
- 声明私有方法
- 把Framework的私有方法公开
- 模拟多继承
3. 底层实现
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);
};
从category结构可以看出:
- 可以添加实例方法,类方法,协议,添加实例属性,类属性(但这里的属性不会自动生成实例变量和对应的get,set方法,需要通过关联对象来实现)
- 不可以添加实例变量
加载调用栈
_objc_init ->map_2_images 镜像->map_images_nlock ->
_read_images->remethodizeClass
把category的实例方法、协议以及属性添加到类上 把category的类方法和协议添加到类的metaclass上
说明: 在remethodizeClass内部核心方法是:attachCategories attachLists: 将含有mcount个元素 的mlists拼接到rw的methods上
特点:
运行时决议 可为系统类添加分类
多总结 多看源码
关联对象
提供了以下API:
// 1. 添加关联对象
void objc_setAssociatedObject(id object, const void* key, id value, objc_AssociationPolicy policy)
// 2. 获得关联对象
id objc_getAssociatedObject(id object, const void* key)
// 3. 移除所有的关联对象
void objc_removeAssociatedObjects(id object)
其中policy属性,是一个枚举值,常见修饰词。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LoD0y0l3-1578018300136)(media/15779461828350/15779542321735.jpg)]
关联对象底层实现依赖四个核心对象: AssocationManager AssocationHashMap objectAssociationMap ObjectAssociation AssocationManager里面存储着某个对象的关联对象Map表,即ObjectAssociationMap,这个表存储了多个关联对象,objectAssociationMap就是我们添加的关联对象.
实现原理
关联本质 AssociationManager管理并在AssociationHashMap存储 所有对象的关联内容都在统一全局容器中。
扩展
定义: Extension是Category的一个特例,类扩展与分类只少了分类的名称,所以又称之为匿名分类。 作用 :
- 声明私有属性
- 声明私有方法
- 声明私有成员变量
特点: 编译时决议
只以声明的形式存在,多数情况下寄生于宿主类中,不能为系统类添加扩展
特点:
- 编译时决议
- 不能为系统类添加扩展
因为运行期,对象的内部布局已经确定,如果添加实例变量会破坏类的内部布局,这对编译性语言是灾难性的。