前言
在iOS開發(fā)中,category作用十分巨大,在實(shí)際項(xiàng)目中,我們可以通過添加一個類的category來實(shí)現(xiàn)任意地方調(diào)用我們已經(jīng)準(zhǔn)備好的方法,或者是對現(xiàn)有的一些類進(jìn)行擴(kuò)展。
最常見的應(yīng)用莫過于為ViewController添加分類,在分類中準(zhǔn)備好方法,這樣一來我們可以在任意控制器去調(diào)用我們準(zhǔn)備好的方法。
由于catagory的特性,使得我們在其中只能添加方法并不能添加屬性,這大大限制了我們的使用。
好在Objective-C的動態(tài)特性為我們帶來了希望。
本文通過利用Objective-C的動態(tài)特性,在運(yùn)行時動態(tài)添加屬性,動態(tài)綁定,達(dá)到category中添加屬性的目的。
分析
首先,我們先看一下property的構(gòu)成
@property的本質(zhì)其實(shí)是 ivar(實(shí)例變量)+getter+setter
也就是說,為category添加屬性的方法,其本質(zhì)上是我們?nèi)藶閯?chuàng)造一個property,通過準(zhǔn)備實(shí)例變量,自行實(shí)現(xiàn)setter方法和getter方法,來達(dá)到目的。
接下來我們看看需要用到的runtime部分。
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
objc_getAssociatedObject
這個方法中需要用到兩個參數(shù),object和key
由于當(dāng)前方法在分類中,并且我們獲取的屬性也是當(dāng)前類下的屬性,object這邊指的是self。
而這里的key代表的是屬性的標(biāo)記,通過這個key來查找對應(yīng)的屬性。
//key的寫法
1、static void *key = &key;
2、static NSString *const key = @"key";
3、static char const * const key = "key";
objc_setAssociatedObject
這個方法中前兩個參數(shù)同上,后兩個參數(shù)分別代表關(guān)聯(lián)的屬性,和關(guān)聯(lián)策略。
關(guān)聯(lián)屬性策略如下,根據(jù)實(shí)際使用選擇關(guān)聯(lián)策略。
enum {
OBJC_ASSOCIATION_ASSIGN = 0, //關(guān)聯(lián)對象的屬性是弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //關(guān)聯(lián)對象的屬性是強(qiáng)引用并且關(guān)聯(lián)對象不使用原子性
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //關(guān)聯(lián)對象的屬性是copy并且關(guān)聯(lián)對象不使用原子性
OBJC_ASSOCIATION_RETAIN = 01401, //關(guān)聯(lián)對象的屬性是copy并且關(guān)聯(lián)對象使用原子性
OBJC_ASSOCIATION_COPY = 01403 //關(guān)聯(lián)對象的屬性是copy并且關(guān)聯(lián)對象使用原子性
};
實(shí)例
在頭文件.h中添加一個property,如:
@property (nonatomic,assign) BOOL animateInvalid;
.m實(shí)現(xiàn):
static char const * const kanimateInvalid = "kanimateInvalid";
#import <objc/runtime.h>
@implementation UIViewController (Associate)
@dynamic animateInvalid;//手動實(shí)現(xiàn)getter和setter
- (BOOL)animateInvalid{
return [objc_getAssociatedObject(self, kanimateInvalid) boolValue];
}
- (void)setAnimateInvalid:(BOOL)animateInvalid{
objc_setAssociatedObject(self, kanimateInvalid, @(animateInvalid), OBJC_ASSOCIATION_ASSIGN);
}
至此在category中添加屬性已經(jīng)完成。掌握方法在實(shí)際項(xiàng)目中能夠發(fā)揮十分大的作用,大大提高我們編程的效率。