iOS 分类(category)的高级详解
iOS 分类(category)的高级详解
作用
1.可以声明一些私有方法,如做SDK一些接口不想暴露给别人看,想自己内部使用,可以通过私有方法,自己内部使用,反过来也可以公开自己的framework中的一些方法给别人看,当没有公开的时候,可以通过加一个分类将私有方法公开。
2.分解体积庞大的类文件,同一功能放到一个 category 中。
3:可以为系统类添加分类,如最常见的 UIView分类,来或得x,y,w,h等
特点
1.运行时决议,编译好分类之后,并没有把方法添加到宿主类上面,运行时添加到宿主类上面
分类中可以添加哪些内容
1.实例方法
2.类方法
3.协议
4.属性(只生成set和get方法,并没有生成实例变量,通过关联对象可以添加实例变量,因为底层的category_t 结构体里面,只存名字实例方法,类方法,协议等信息,没有存实例变量的)
分类调用栈
分类倒序遍历,最先访问最后编译的分类,分类有多个,最后编译的分类的方法会生效
分类添加的方法可以“覆盖”原来类的方法,因为在runtime源码中,有memmove,会把分类中的方法移动到原来类方法的前面,所以会执行分类中的方法,因为有方法选择器,当匹配到了分类中的方法之后,就会执行,分类中的方法,但原来类的方法依然存在。
同名分类方法谁能生效取决于编译顺序,最后被编译的分类,会最先生效
名字相同的分类会引起编译报错
为分类添加实例变量
可以通过关联对象的方式为分类添加成员变量,objc_getAssociatedObjc , objc_setAssociatedObject
,通过关联对象为原来添加成员变量,并没有添加到宿主类上面,关联对象由 AssociationManager 管理并在 AssociationsHashMap 中,所有对象的关联内容都在同一个全局容器中,为不同的类添加也都在一个全局容器中。在runtime源码中,创建一个对象的时候,会先判断值是否为空,如果为nil,那么就证明将之前设置的值移除掉,如果不为空,会先判断,是否能找到 ObjcAssociationMap
,如果没有找到会创建一个map,如果找到了,会用新的值替换掉原来map中的值,大概可以描述为下面的 json 形式
/*
加入下面是为某个类添加的成员变量
*/
{
/*
类1:
@property(copy)NSString *name;
*/
// 类1
// 最外面的 key 为被关联的对象,value 是一个 ObjcAssociationMap ,ObjcAssociationMap 中,@selector 为被关联的值得 key,policy 为策略,是 retain还是copy 等
"0x1242342432":{
"@selector(name)":{
"value":"sunchengxiu",
"policy":"copy"
}
},
// 类2
"0x54354253223":{
"@selector(age)":{
"value":"25"
"policy":"retain"
}
}
}