1. 程式人生 > >給分類(Category)新增屬性

給分類(Category)新增屬性

http://www.jianshu.com/p/3cbab68fb856

遇到一個問題,寫了一個分類,但原先類的屬性不夠用。新增一個屬性,呼叫的時候崩潰了,說是找不到getter、setter方法。查了下文件發現,OC的分類允許給分類新增屬性,但不會自動生成getter、setter方法。有沒有解決方案呢?有,通過執行時建立關聯引用。接下來以新增一個這樣的屬性為例:

@property (nonatomic, copy) NSString *str;

1、引入執行時標頭檔案。

#import <objc/runtime.h>

2、在匿名分類或者標頭檔案中新增屬性。區別是:匿名分類中新增的是私有屬性,只在本類中可以使用,類的例項中不可以使用。標頭檔案中新增的在類的例項中也可以使用。

//分類的標頭檔案
@interface ClassName (CategoryName)
//我要新增一個例項也可以訪問的變數所以就寫在這裡了
@property (nonatomic, strong) NSString *str;
@end

//匿名分類
@interface ClassName ()

@end

3、在實現裡面寫要新增屬性的getter、setter方法。

@implementation ClassName (CategoryName) 

-(void)setStr:(NSString *)str  
{  
    objc_setAssociatedObject(self
, &strKey, str, OBJC_ASSOCIATION_COPY); } -(NSString *)str { return objc_getAssociatedObject(self, &strKey); } @end

setStr:方法中使用了一個objc_setAssociatedObject的方法,這個方法有四個引數,分別是:源物件,關聯時的用來標記是哪一個屬性的key(因為你可能要新增很多屬性),關聯的物件和一個關聯策略。

用來標記是哪一個屬性的key常見有三種寫法,但程式碼效果是一樣的,如下:

//利用靜態變數地址唯一不變的特性
1static void *strKey = &strKey; 2static NSString *strKey = @"strKey"; 3static char strKey;

關聯策略是個列舉值,解釋如下:

enum {
    OBJC_ASSOCIATION_ASSIGN = 0, //關聯物件的屬性是弱引用 

    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //關聯物件的屬性是強引用並且關聯物件不使用原子性

    OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //關聯物件的屬性是copy並且關聯物件不使用原子性

    OBJC_ASSOCIATION_RETAIN = 01401, //關聯物件的屬性是copy並且關聯物件使用原子性

    OBJC_ASSOCIATION_COPY = 01403 //關聯物件的屬性是copy並且關聯物件使用原子性
};

4、完成後的整體程式碼如下:

.h檔案

//分類的標頭檔案
@interface ClassName (CategoryName)
@property (nonatomic, strong) NSString *str;
@end

.m檔案

//實現檔案
#import "ClassName + CategoryName.h"
#import <objc/runtime.h>

static void *strKey = &strKey;

@implementation ClassName (CategoryName) 
-(void)setStr:(NSString *)str  
{  
    objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);  
}  

-(NSString *)str  
{  
    return objc_getAssociatedObject(self, &strKey);  
}
@end