众所周知,类别(Category)是不能直接添加属性的,但是可以利用Runtime来关联对象添加属性。
首先,说一下类别(Category)的优缺点和作用
优点:
不需要通过增加子类而增加现有类的行为(方法),且类目中的方法与原始类方法基本没有区别;
通过类目可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性;
缺点:
无法向类目添加实例变量,如果需要添加实例变量,只能通过定义子类的方式;
类目中的方法与原始类以及父类方法相比具有更高优先级,如果覆盖父类的方法,可能导致super消息的断裂。因此,最好不要覆盖原始类中的方法。
类别的作用
给系统原有类添加方法,不能扩展属性。
如果类别中方法的名字跟系统的方法名一样,在调用的时候类别中的方法优先级更高;
分散类的实现:如:
- (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section
原本属于NSIndexPath的方法,
但因为这个方法经常使用的表的时候调用、跟表的关系特别密切,因此把这个方法一类别的形式、声明在UITableView.h中。
声明私有方法,某一个方法只实现,不声明,相当于私有方法。
类别不能声明变量,类别不可以直接添加属性,但是可以利用Runtime来关联对象添加属性。
property描述setter方法,就不会报错。
添加属性
类别可以为已有的类添加方法,但是却不能直接添加属性,因为即使你添加了@property,它既不会生成实例变量,也不会生成setter、getter方法,即使你添加了也无法使用。
所以我们首先需要自己去添加setter、getter方法,这个好办,直接在.m文件里加就可以了,但是要真正添加可以使用的属性,还需要利用Runtime来关联对象,我们在setter方法里关联一个对象,在getter方法里获取对应key关联的对象,就可以啦,代码如下:
//UINavigationController+Cloudox.h文件
import <UIKit/UIKit.h>
@interface UINavigationController (Cloudox)
@property (copy, nonatomic) NSString *cloudox;
@end
//UINavigationController+Cloudox.m文件
import "UINavigationController+Cloudox.h"
import <objc/runtime.h>
@implementation UINavigationController (Cloudox)
//定义常量 必须是C语言字符串
static char *CloudoxKey = "CloudoxKey";
-(void)setCloudox:(NSString )cloudox{
/
objc_AssociationPolicy参数使用的策略:
OBJC_ASSOCIATION_ASSIGN; //assign策略
OBJC_ASSOCIATION_COPY_NONATOMIC; //copy策略
OBJC_ASSOCIATION_RETAIN_NONATOMIC; // retain策略
OBJC_ASSOCIATION_RETAIN;
OBJC_ASSOCIATION_COPY;
*/
/*
关联方法:
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
参数:
* id object 给哪个对象的属性赋值
const void *key 属性对应的key
id value 设置属性值为value
objc_AssociationPolicy policy 使用的策略,是一个枚举值,和copy,retain,assign是一样的,手机开发一般都选择NONATOMIC
*/
objc_setAssociatedObject(self, CloudoxKey, cloudox, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(NSString *)cloudox{
return objc_getAssociatedObject(self, CloudoxKey);
}
@end
注意要使用Runtime需要 import runtime 的框架,如代码所示。