1. 程式人生 > >iOS中OC給Category新增屬性

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中的關聯物件技術就可以輕鬆達到了。