分类
目录:
一、介绍(介绍这点摘录过来的,不想码字了~)
1.分类的作用?
声明私有方法,分解体积大的类文件,把framework的私有方法公开
2.分类的特点
运行时决议,可以为系统类添加分类 。
说得详细些,在运行时时期,将 Category 中的实例方法列表、协议列表、属性列表添加到主类中后(所以Category中的方法在方法列表中的位置是在主类的同名方法之前的),然后会递归调用所有类的 load 方法,这一切都是在main函数之前执行的。
3.分类可以添加哪些内容?
实例方法,类方法,协议,属性(添加getter和setter方法,并没有实例变量,添加实例变量需要用关联对象)
4.如果工程里有两个分类A和B,两个分类中有一个同名的方法,哪个方法最终生效?
取决于分类的编译顺序,最后编译的那个分类的同名方法最终生效,而之前的都会被覆盖掉(这里并不是真正的覆盖,因为其余方法仍然存在,只是访问不到,因为在动态添加类的方法的时候是倒序遍历方法列表的,而最后编译的分类的方法会放在方法列表前面,访问的时候就会先被访问到,同理如果声明了一个和原类方法同名的方法,也会覆盖掉原类的方法)。
5.如果声明了两个同名的分类会怎样?
会报错,所以第三方的分类,一般都带有命名前缀
6.分类能添加成员变量吗?
不能。只能通过关联对象(objc_setAssociatedObject)来模拟实现成员变量,但其实质是关联内容,所有对象的关联内容都放在同一个全局容器哈希表中:AssociationsHashMap,由AssociationsManager统一管理。
作者:Theendisthebegi
链接:https://www.jianshu.com/p/e70bac443cf2
二、为什么分类不能添加属性(这个是看了别人的博客,自己代码验证下来的总结)
我们先创建一个LPLObject类,在controller的touchbegin方法中调用如下:
我们分别打印了LPLObject类的成员变量列表,属性列表,方法列表。发现只有name,age两个属性,_成员变量,以及其set,get方法。
接下来我们开始为LPLObject添加分类。
可以看到分类的.m文件中,警告我们我们并没有为lplName属性实现set,get方法。现在去控制器重新打印一下输出。
从打印可以看出,分类为主类添加的属性lplName,只是将添加的属性加入到了主类的属性列表中。而 _成员变量 以及 该属性的set,get方法,并没有被生成。所以当我们使用点语法隐式调用set,get方法时,会报错,提示我们没有实现存取方法。
三、有什么方法可以处理上面的问题
有同学可能会想,既然没有实现set,get方法,那我们自己实现一下不就好了吗。我们要注意,分类添加的属性,是不会为我们生成(_成员变量)的,那么我们就无法在存取方法中进行赋值操作。
那么怎么办呢,解决办法也是有的,使用runtime进行对象关联即可。上代码
这样,在外部调用的时候,就可以通过存取方法进行属性的修改了。在控制器重新打印一次。
可以看到lplName属性的存取方法已经被添加到主类的方法列表中。但是要注意(_成员变量仍然是没有被添加的!!!)
四、runtime动态关联对象添加属性底层实现原理
https://blog.csdn.net/olsq93038o99s/article/details/80878983(偶然看到的大佬写的runtime关联对象底层原理)
网友评论