引:
很多人知道可以用Category給已有的類添加一些新方法笔横,但是不同于swift中的extension吹缔,Objective-C中的Category(類別)是不支持直接添加屬性的厢塘,那如果就是需要添加新的屬性怎么辦呢?有一個辦法礁叔,使用Runtime中的關(guān)聯(lián)對象技術(shù)就可以實(shí)現(xiàn)琅关。關(guān)于Runtime的說明可以查看這篇博客:傳送門:OC中Runtime淺析
Category(類別):
對于不熟悉Category的人讥蔽,這里也先說明一下Category是什么以及怎么創(chuàng)建Category新症。
由于一些特殊的需要徒爹,我們可能要給現(xiàn)有的類添加一些新的方法,這個需求用繼承也可以做到界阁,但是會顯得比較重,這時候就可以用Category來達(dá)到目的胖喳,創(chuàng)建一個已有類的Category泡躯,可以給這個類添加你需要的方法,在使用的時候丽焊,只需要import你創(chuàng)建的Category较剃,在使用的時候還是使用原來的類,但是你會驚奇的發(fā)現(xiàn)他支持你自己在Category中添加的方法技健。
我們看到的一些名為類似“UINavigationController+Cloudox.h”的文件就是類別了重付。
那么怎么創(chuàng)建類別呢?
在工程中按住command+N來添加新文件凫乖,選擇Objectiv-C File:
在出來的界面中的File Type選擇Category,就是創(chuàng)建類別文件了弓颈,F(xiàn)ile填寫我們要加在類別尾巴上的名字帽芽,Class選擇你要添加類別的已有類,這里我們?yōu)閁INavigationController添加類別:
類別文件這樣就創(chuàng)建成功了翔冀。
添加屬性
類別可以為已有的類添加方法,但是卻不能直接添加屬性泽论,因?yàn)榧词鼓闾砑恿薂property,它既不會生成實(shí)例變量鹦赎,也不會生成setter锁施、getter方法膊毁,即使你添加了也無法使用。
所以我們首先需要自己去添加setter荆秦、getter方法,這個好辦,直接在.m文件里加就可以了刑桑,但是要真正添加可以使用的屬性拱礁,還需要利用Runtime來關(guān)聯(lián)對象,關(guān)于關(guān)聯(lián)對象的技術(shù)可以看傳送門:OC中Runtime淺析烛芬,這里只講怎么用來添加屬性,我們在setter方法里關(guān)聯(lián)一個對象,在getter方法里獲取對應(yīng)key關(guān)聯(lián)的對象揍堰,就可以啦,代碼如下季希,很簡單:
//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參數(shù)使用的策略:
OBJC_ASSOCIATION_ASSIGN; //assign策略
OBJC_ASSOCIATION_COPY_NONATOMIC; //copy策略
OBJC_ASSOCIATION_RETAIN_NONATOMIC; // retain策略
OBJC_ASSOCIATION_RETAIN;
OBJC_ASSOCIATION_COPY;
*/
/*
關(guān)聯(lián)方法:
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
參數(shù):
* id object 給哪個對象的屬性賦值
const void *key 屬性對應(yīng)的key
id value 設(shè)置屬性值為value
objc_AssociationPolicy policy 使用的策略,是一個枚舉值武学,和copy默赂,retain疾捍,assign是一樣的,手機(jī)開發(fā)一般都選擇NONATOMIC
*/
objc_setAssociatedObject(self, CloudoxKey, cloudox, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(NSString *)cloudox{
return objc_getAssociatedObject(self, CloudoxKey);
}
@end
注意要使用Runtime需要 import runtime 的框架,如代碼所示。
現(xiàn)在我們試試效果错负,我們按照平常的方式用UINavigationController包裝一個控制器作為根視圖:
// AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ViewController *vc = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;
return YES;
}
這個視圖控制器中我們需要導(dǎo)入我們的類別文件诚镰,然后我們就會發(fā)現(xiàn)我們能夠通過self.navigationController獲取到我們新添加的名為“cloudox”的屬性了镰踏!我們可以給這個NSString類型的屬性賦值,然后獲取它進(jìn)行顯示:
#import "UINavigationController+Cloudox.h"
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Demo";
self.view.backgroundColor = [UIColor lightGrayColor];
// 給UINavigationController新加的屬性賦值
self.navigationController.cloudox = @"Hey,this is category's new property!";
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width-300)/2, 100, 300, 50)];
label.textColor = [UIColor whiteColor];
label.textAlignment = NSTextAlignmentCenter;
label.text = self.navigationController.cloudox;
[self.view addSubview:label];
}
效果如下:
正常獲取到并且顯示藐俺,非常棒菱父。
結(jié)
以上就是給Category添加屬性的方法啦,不難野崇,只要了解Runtime中的關(guān)聯(lián)對象技術(shù)就可以輕松達(dá)到了蕴侣。
示例工程:https://github.com/Cloudox/CategoryAddPropertyDemo