iOS 分类(category)的高级详解

2019-12-13  本文已影响0人  孙掌门

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"
            }
        }
    }
    

上一篇下一篇

猜你喜欢

热点阅读