iOS中category即:类别 ;extension 为扩张
一.category
类别是一种为现有的类添加新方法的方式。
利用Objective-C的动态运行时分配机制,Category提供了一种比继承(inheritance)更为简洁的方法来对class进行扩展,无需创建对象类的子类就能为现有的类添加新方法,可以为任何已经存在的class添加方法,包括那些没有源代码的类(如某些框架类)。
1.类别的局限:(1)无法向类别中添加新的实例变量,类别没有位置容纳实例变量。如果一定要添加实例变量,可以采用runtime 库objc_setAssociatedObject / objc_getAssociatedObject 函数来解决。objc_setAssociatedObject 就是将一个对象跟另一个对象进行关联,并用一个key来标示,objc_getAssociatedObject 就是用这个key来拿到与receiver相关联的一个对象。
注意:必须使用@dynamic来让编译器知道我们自己实现setter/getter方法(如果对于@dynamic有疑问,请参见:http://stackoverflow.com/questions/1160498/synthesize-vs-dynamic-what-are-the-differences)
不能使用@synthesize(也不能@dynamic 和@synthesize都不写,什么都不写在最新的xcode里是默认@synthesize),@synthesize会自动生成成员变量,并自动生成setter/getter方法。
最后,objc_setAssociatedObject 的关联的policy 可以根据自己的需求使用,这个例子使用 OBJC_ASSOCIATION_RETAIN_NONATOMIC来标示一个strong reference来指向被关联的对象。
(2)名称冲突,即当类别中的方法名与原始类中的名称相同的时候,类别具有更高的优先级。类别的方法将完全取代原始方法而无法再使用原始方法。
2.类别的作用
类别的作用主要有三个:
(1)可以将类的实现分散到多个不同的文件或者不同的框架中,方便代码的管理。也可以对框架提供类的扩展(没有源码,不能修改)。
(2)创建对私有方法的前向引用:如果其他类中的方法未实现,在你访问其他类的私有方法时编译器报错这时使用类别,在类别中声明这些方法(不必提供方法实现),编译器就不会再产生警告
(3)向对象添加非正式协议:创建一个NSObject的类别称为“创建一个非正式协议”,因为可以作为任何类的委托对象使用。
二.Extension 的使用
首先还是需要创建相关类的扩展,即方法的声明,然后在需要扩张的类中引入头文件,然后实现声明的方法。
三.Category 与Extension 的区别
1.形式上看:extension 是匿名的category
2.extension中声明的方法需要在mainimplementation中实现,而category 不做强制要求
3.extension 可以添加属性、成员变量,而category 一般不可以。
网友评论
这段话的说法是不严谨的,类别并不是有更高的优先级,在运行时,类与类别的运行循序有关系。
假如类别和类都有同一个方法 methodA,那么在 runtime 期要先把类中的 method 放入方法栈里,然后再放类别中 method A,这样是在方法栈中放了两个 methodA。
在调用 methodA 时,会遍历这个类的方法栈,只要发现 methodA 就会停止遍历,所以自然屌用的就是类别中的 methodA 了。