正常情况下,创建的分类只能添加方法而不能添加属性,但是具体什么原因,下面我来根据我实际实验得出的结论简单讲讲。
首先,如果在普通的类里添加@property,那么系统会自动生成带“_”的成员变量,以及该变量的setter和getter方法。
那么,如果在分类里添加@property的话,会怎么样呢?通过打印发现,在分类里添加@property,系统并不能生成带“_”的成员变量,自然也没有实现setter和getter方法,这时候如果控制器调用点方法,程序运行时就会报错,显示找不到该方法。
如上图,在分类里添加height属性后,即使实现了setter和getter方法,也仍然没有添加带“_”的成员变量,也就是说,在setter和getter方法里仍然不能直接访问以下划线开头的成员变量,因为在分类里用@property声明属性时系统并没有添加以“_”开头的成员变量。此时如果一定要达到添加的目的,就可以使用运行时的关联对象。代码如下:
当然也可以在setter和getter方法里访问该类其他的属性,比如在UIView的分类的里添加x、y属性,可以直接返回self.frame.origin.x和self.frame.origin.y。
总结
在分类里使用@property声明属性,只是将该属性添加到该类的属性列表,并声明了setter和getter方法,但是没有生成相应的成员变量,也没有实现setter和getter方法。所以说分类不能添加属性。但是在分类里使用@property声明属性后,又实现了setter和getter方法,那么在这个类以外可以正常通过点语法给该属性赋值和取值。要注意的一点是:在分类中声明了一个属性的时候,就要手动的去实现这个属性的set和get方法,这个时候就要用到运行时机制了,关联上去这个属性的存取过程。就是说,在分类里使用@property声明属性,又实现了setter和getter方法后,可以认为给这个类添加上了属性。
再总结
准确的说,其实分类是可以添加属性的,但是一定添加不了成员变量。成员变量和属性一定要分清楚。
借用一个博主的总结:其实属性是可以添加的。只是说现在Xcode自动会给属性生成成员变量让大家对这个概念有点混淆。Property是Property,Ivar是Ivar。
分类里面不能添加Ivar是因为分类本身并不是一个真正的类,它并没有自己的ISA。有兴趣可以研究一下类是怎么被创建出来的,类最开始生成了很多基本属性,比如IvarList,MethodList,分类只会将自己的method attach到主类,并不会影响到主类的IvarList。这就是为什么分类里面不能增加成员变量的原因。
_cmd
_cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例。