iOS 給分類(Category文件)添加屬性

一直都知道分類里面添加屬性,會提示黃色警告,使用的時(shí)候運(yùn)行到這里會crash,那么就真的不能給分類里面添加屬性嗎?答案當(dāng)然是可以的,那么怎么添加呢,那么我們先創(chuàng)建一個(gè)Person的分類,繼承NSObject,在.h文件里面添加一條name的屬性
@property (nonatomic, copy) NSString *name;

當(dāng)然也可以在.m匿名分類里面添加屬性,只是這樣的屬性只能在這個(gè)分類里面使用,不能在類的實(shí)例中使用。.h文件中添加的在類的實(shí)例中也可以使用。然后在.m引入runtime的頭文件
#import <objc/runtime.h> 或者 #import <objc/message.h> //這兩種都可以

接下來先在.m文件為我們的name屬性添加一個(gè)key
static NSString *nameKey = @"nameKey"; //name的key

這時(shí)候執(zhí)行Xcode命令command + b,在匿名分類里面就會出現(xiàn)黃色警報(bào),如下

Property 'name' requires method 'name' to be defined - use @dynamic or provide a method implementation in this category

運(yùn)行會crash并提示

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSObject setName:]: unrecognized selector sent to instance 0x600000002db0'

這句崩潰的提示是找不到setName:方法,下面就是給分類屬性添加setter方法

- (void)setName:(NSString *)name {~~
    objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

setName:里面使用了一個(gè)objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)方法,這個(gè)方法有四個(gè)參數(shù),分別是:
1.源對象(self)
2.關(guān)聯(lián)時(shí)的用來標(biāo)記是哪一個(gè)屬性的key(因?yàn)槟憧赡芤砑雍芏鄬傩?,這里咱們填寫的是&nameKey)
3.關(guān)聯(lián)的對象(name)
4.一個(gè)關(guān)聯(lián)策略(OBJC_ASSOCIATION_COPY_NONATOMIC)。

在匿名分類里面寫上上述代碼后,執(zhí)行Xcode命令command+b,此時(shí)匿名分類提示黃色警報(bào)

Property 'name' requires method 'name' to be defined - use @dynamic or provide a method implementation in this category

如果運(yùn)行給分類里面的name屬性賦值(執(zhí)行setter方法)是沒有問題的

    NSObject *objc = [[NSObject alloc] init];
    objc.name = @"almost";

但是如果獲取name的值,例如執(zhí)行NSLog(@"%@", objc.name);,那么運(yùn)行到這里就會crash并提示

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSObject name]: unrecognized selector sent to instance 0x6000000064a0'

這句話的意思就是你沒有實(shí)現(xiàn)name的getter方法,將getter方法在匿名類實(shí)現(xiàn)

- (NSString *)name {
    return objc_getAssociatedObject(self, &nameKey);
}

在這里用到了objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)這個(gè)方法,這個(gè)方法有兩個(gè)參數(shù),填寫方法參照setter方法

//利用靜態(tài)變量地址唯一不變的特性
static NSString *nameKey = @"nameKey";
static void *nameKey = &nameKey;
static char nameKey;

關(guān)聯(lián)策略是個(gè)枚舉值,解釋如下:

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,             //好比assign關(guān)聯(lián)對象的屬性是弱引用,
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,   //好比strong, nonatomic,關(guān)聯(lián)對象的屬性是強(qiáng)引用并且關(guān)聯(lián)對象不使用原子性,
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,     //好比copy, nonatomic,關(guān)聯(lián)對象的屬性是copy并且關(guān)聯(lián)對象不使用原子性
    OBJC_ASSOCIATION_RETAIN = 01401,         //好比strong, atomic,關(guān)聯(lián)對象的屬性是copy并且關(guān)聯(lián)對象使用原子性
    OBJC_ASSOCIATION_COPY = 01403            //好比copy, atomic,關(guān)聯(lián)對象的屬性是copy并且關(guān)聯(lián)對象使用原子性
};
那么使用runtime給分類添加屬性的全部代碼就是

.h文件

#import <Foundation/Foundation.h>

@interface NSObject (Person)

@property (nonatomic, copy) NSString *name;

@end

.m文件

#import "NSObject+Person.h"
#import <objc/runtime.h> /*或者 #import <objc/message.h>*/
static NSString *nameKey = @"nameKey"; //那么的key

@interface NSObject ()

@end

@implementation NSObject (Person)

/**
 setter方法
 */
- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

/**
 getter方法
 */
- (NSString *)name {
    return objc_getAssociatedObject(self, &nameKey);
}
@end

在其他類的實(shí)例種中調(diào)用

- (void)viewDidLoad {
    NSObject *objc = [[NSObject alloc] init];
    objc.name = @"almost";
    NSLog(@"%@", objc.name);
}

另附上代碼,點(diǎn)擊代碼地址或點(diǎn)擊鏈接https://github.com/173323222/CategoryProperty

點(diǎn)擊跳轉(zhuǎn)到關(guān)聯(lián)對象的結(jié)構(gòu)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,099評論 0 9
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • 假期第二日 邂逅 水清覺得她的兩個(gè)乳房如石頭般堅(jiān)硬,乳汁不停地往外流,濕了她的睡衣和被褥。水清躺在床上輾轉(zhuǎn)...
    Domke清水閱讀 394評論 0 1
  • 十載可遇風(fēng)雪天, 千里飛舞臨江南, 學(xué)童嬉戲遲未還, 冰封路面行不便, 梅俏枝頭花正繁, 忽迎隆冬三九寒, 素裹大...
    墨度閱讀 508評論 1 4
  • 約融都面試的前一天下午,剛寫完小余教育的面試總結(jié),結(jié)果小余教育的HR打電話過來,問我什么時(shí)候能報(bào)道???...
    吳_旭東閱讀 560評論 1 0

友情鏈接更多精彩內(nèi)容