在面試的時(shí)候哮针,我們也許會(huì)遇到這樣的面試題:在不使用繼承的情況下亿傅,如何給一個(gè)類(lèi)添加屬性?其實(shí)給類(lèi)添加屬性還可以創(chuàng)建分類(lèi)翠桦,利用iOS runtime ,關(guān)聯(lián)對(duì)象的方法給類(lèi)添加屬性胳蛮。
什么是關(guān)聯(lián)對(duì)象销凑?
Associated Objects(關(guān)聯(lián)對(duì)象)或者叫作關(guān)聯(lián)引用(Associative References),是作為Objective-C 2.0 運(yùn)行時(shí)功能被引入到 Mac OS X 10.6 Snow Leopard(及iOS4)系統(tǒng)仅炊。與它相關(guān)在<objc/runtime.h>中有3個(gè)C函數(shù)斗幼,它們可以讓對(duì)象在運(yùn)行時(shí)關(guān)聯(lián)任何值:
//設(shè)置關(guān)聯(lián)對(duì)象
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//獲取關(guān)聯(lián)對(duì)象
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
//斷開(kāi)對(duì)象的關(guān)聯(lián)(它會(huì)斷開(kāi)所有的關(guān)聯(lián),不建議使用抚垄。只有在需要把對(duì)象恢復(fù)到“原始狀態(tài)”的時(shí)候才會(huì)使用這個(gè)函數(shù))
OBJC_EXPORT void objc_removeAssociatedObjects(id object)
其實(shí)簡(jiǎn)單點(diǎn)說(shuō)就是把兩個(gè)沒(méi)有關(guān)系的東西蜕窿,關(guān)聯(lián)在一起。
設(shè)置關(guān)聯(lián)對(duì)象(Set方法)
//設(shè)置關(guān)聯(lián)對(duì)象
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
這個(gè)方法有4個(gè)參數(shù):
1.源對(duì)象呆馁;
2.關(guān)鍵字:這個(gè) key 值必須保證是一個(gè)對(duì)象級(jí)別的唯一常量桐经。有以下三種推薦的 key 值:
1.聲明 static char kAssociatedObjectKey,使用 &kAssociatedObjectKey 作為 key 值;
2.聲明 static void *kAssociatedObjectKey = &kAssociatedObjectKey 浙滤,使用 kAssociatedObjectKey 作為 key 值次询;
3.用 selector ,使用 getter 方法的名稱作為 key 值瓷叫。
3.關(guān)聯(lián)的對(duì)象屯吊;
4.關(guān)聯(lián)策略:有五種關(guān)聯(lián)策略可供選擇:
/**
* OBJC_ASSOCIATION_ASSIGN
等價(jià)于@property (assign) ,
@property (unsafe_unretained)
弱引用關(guān)聯(lián)對(duì)象
* OBJC_ASSOCIATION_RETAIN_NONATOMIC
等價(jià)于@property (strong, nonatomic)
強(qiáng)引用關(guān)聯(lián)對(duì)象摹菠,且為非原子操作
* OBJC_ASSOCIATION_COPY_NONATOMIC
等價(jià)于@property (copy, nonatomic)
復(fù)制關(guān)聯(lián)對(duì)象盒卸,且為非原子操作
* OBJC_ASSOCIATION_RETAIN
等價(jià)于@property (strong, atomic)
強(qiáng)引用關(guān)聯(lián)對(duì)象,且為原子操作
* OBJC_ASSOCIATION_COPY
等價(jià)于@property (copy, atomic)
復(fù)制關(guān)聯(lián)對(duì)象次氨,且為原子操作
其中蔽介,第 2 種與第 4 種、第 3 種與第 5 種關(guān)聯(lián)策略的唯一差別就在于操作是否具有原子性。
*/
獲取關(guān)聯(lián)對(duì)象(get方法)
//獲取關(guān)聯(lián)對(duì)象
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
斷開(kāi)對(duì)象的關(guān)聯(lián)
我們不需要主動(dòng)調(diào)用removeAssociated來(lái)接觸關(guān)聯(lián)的對(duì)象虹蓄,如果需要解除指定的對(duì)象犀呼,可以使用setAssociatedObject置nil來(lái)實(shí)現(xiàn)。
吃個(gè)??:
.h
#import <UIKit/UIKit.h>
@interface UIViewController (Alpha)
@property (nonatomic, copy) NSString *strNavBarBgAlpha;
@end
.m
@implementation UIViewController (Alpha)
- (void)setStrNavBarBgAlpha:(NSString *)strNavBarBgAlpha {
//設(shè)置關(guān)聯(lián)對(duì)象
objc_setAssociatedObject(self, @selector(strNavBarBgAlpha), strNavBarBgAlpha, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)strNavBarBgAlpha {
//獲取關(guān)聯(lián)對(duì)象
return objc_getAssociatedObject(self, @selector(strNavBarBgAlpha));
}
@end
調(diào)用:
self.strNavBarBgAlpha = @"1.0";