iOS中OC給Category新增屬性
引:
很多人知道可以用Category給已有的類新增一些新方法,但是不同於swift中的extension,Objective-C中的Category(類別)是不支援直接新增屬性的,那如果就是需要新增新的屬性怎麼辦呢?有一個辦法,使用Runtime中的關聯物件技術就可以實現。關於Runtime的說明可以檢視這篇部落格:傳送門:OC中Runtime淺析
Category(類別):
對於不熟悉Category的人,這裡也先說明一下Category是什麼以及怎麼建立Category。
由於一些特殊的需要,我們可能要給現有的類新增一些新的方法,這個需求用繼承也可以做到,但是會顯得比較重,這時候就可以用Category來達到目的,建立一個已有類的Category,可以給這個類新增你需要的方法,在使用的時候,只需要import你建立的Category,在使用的時候還是使用原來的類,但是你會驚奇的發現他支援你自己在Category中新增的方法。
我們看到的一些名為類似“UINavigationController+Cloudox.h”的檔案就是類別了。
那麼怎麼建立類別呢?
在工程中按住command+N來新增新檔案,選擇Objectiv-C File:
在出來的介面中的File Type選擇Category,就是建立類別檔案了,File填寫我們要加在類別尾巴上的名字,Class選擇你要新增類別的已有類,這裡我們為UINavigationController新增類別:
類別檔案這樣就建立成功了。
新增屬性
類別可以為已有的類新增方法,但是卻不能直接新增屬性,因為即使你添加了@property,它既不會生成例項變數,也不會生成setter、getter方法,即使你添加了也無法使用。
所以我們首先需要自己去新增setter、getter方法,這個好辦,直接在.m檔案里加就可以了,但是要真正新增可以使用的屬性,還需要利用Runtime來關聯物件,關於關聯物件的技術可以看傳送門:OC中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 的框架,如程式碼所示。
現在我們試試效果,我們按照平常的方式用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;
}
這個檢視控制器中我們需要匯入我們的類別檔案,然後我們就會發現我們能夠通過self.navigationController獲取到我們新新增的名為“cloudox”的屬性了!我們可以給這個NSString型別的屬性賦值,然後獲取它進行顯示:
#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];
}
效果如下:
正常獲取到並且顯示,非常棒。
結
以上就是給Category新增屬性的方法啦,不難,只要瞭解Runtime中的關聯物件技術就可以輕鬆達到了。