很多開(kāi)源庫(kù)都使用了關(guān)聯(lián)鞍盗,我們可以不用修改類的定義而為其對(duì)象增加存儲(chǔ)空間肢础。這在我們無(wú)法訪問(wèn)到類的源碼的時(shí)候或者是考慮到二進(jìn)制兼容性的時(shí)候是非常有用喂分。
關(guān)聯(lián)是基于關(guān)鍵字的聚假,因此块蚌,我們可以為任何對(duì)象增加任意多的關(guān)聯(lián),每個(gè)都使用不同的關(guān)鍵字即可膘格。關(guān)聯(lián)是可以保證被關(guān)聯(lián)的對(duì)象在關(guān)聯(lián)對(duì)象的整個(gè)生命周期都是可用的(在垃圾自動(dòng)回收環(huán)境下也不會(huì)導(dǎo)致資源不可回收)峭范。
在類的定義之外為類增加額外的存儲(chǔ)空間
- objc_setAssociatedObject
/**
* Sets an associated value for a given object using a given key and association policy.
*
* @param object The source object for the association.
* @param key The key for the association.
* @param value The value to associate with the key key for object. Pass nil to clear an existing association.
* @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
*
* @see objc_setAssociatedObject
* @see objc_removeAssociatedObjects
*/
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
objc_setAssociatedObject把一個(gè)對(duì)象與另外一個(gè)對(duì)象進(jìn)行關(guān)聯(lián)。該函數(shù)需要四個(gè)參數(shù):源對(duì)象瘪贱,關(guān)鍵字纱控,關(guān)聯(lián)的對(duì)象和一個(gè)關(guān)聯(lián)策略
關(guān)聯(lián)策略
/* Associative References */
/**
* Policies related to associative references.
* These are options to objc_setAssociatedObject()
*/
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
//指定一個(gè)弱引用相關(guān)聯(lián)的對(duì)象
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
//強(qiáng)引用關(guān)聯(lián)對(duì)象辆毡,非原子操作
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
// 復(fù)制關(guān)聯(lián)對(duì)象,非原子操作
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
// 強(qiáng)引用關(guān)聯(lián)對(duì)象甜害,原子操作
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
// 復(fù)制關(guān)聯(lián)對(duì)象舶掖,非原子操作
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
OBJC_ASSOCIATION_ASSIGN 等價(jià)于 @property(assign)。
OBJC_ASSOCIATION_RETAIN_NONATOMIC等價(jià)于 @property(strong, nonatomic)尔店。
OBJC_ASSOCIATION_COPY_NONATOMIC等價(jià)于@property(copy, nonatomic)眨攘。
OBJC_ASSOCIATION_RETAIN等價(jià)于@property(strong,atomic)。
OBJC_ASSOCIATION_COPY等價(jià)于@property(copy, atomic)嚣州。
/**
//獲取關(guān)聯(lián)的對(duì)象
* Returns the value associated with a given object for a given key.
*
* @param object The source object for the association.
* @param key The key for the association.
*
* @return The value associated with the key \e key for \e object.
*
* @see objc_setAssociatedObject
*/
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
//斷開(kāi)關(guān)聯(lián)
//或者直接使用objc_setAssociatedObject函數(shù)期犬,傳入nil值即可
/**
* Removes all associations for a given object.
*
* @param object An object that maintains associated objects.
*
* @note The main purpose of this function is to make it easy to return an object
* to a "pristine state”. You should not use this function for general removal of
* associations from objects, since it also removes associations that other clients
* may have added to the object. Typically you should use \c objc_setAssociatedObject
* with a nil value to clear an association.
*
* @see objc_setAssociatedObject
* @see objc_getAssociatedObject
*/
OBJC_EXPORT void objc_removeAssociatedObjects(id object)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
* 例子
//給一個(gè)可變數(shù)組添加一個(gè)關(guān)聯(lián)
static char overviewKey;
NSMutableArray * marrDemo =[[NSMutableArray alloc] initWithObjects:@"1", @"2", @"3", nil];
NSString * overview = [[NSString alloc] initWithFormat:@"%@",@"First three numbers"];
objc_setAssociatedObject(marrDemo, &overviewKey, overview, OBJC_ASSOCIATION_RETAIN);
//獲取相關(guān)聯(lián)的對(duì)象
NSString * associatedObject = (NSString *)objc_getAssociatedObject(marrDemo, &overviewKey);
//斷開(kāi)關(guān)聯(lián)
//斷開(kāi)關(guān)聯(lián)是使用objc_setAssociatedObject函數(shù),傳入nil值即可
objc_setAssociatedObject(marrDemo, &overviewKey, nil, OBJC_ASSOCIATION_RETAIN);
分類避诽,是不能添加屬性的,調(diào)用會(huì)崩潰的璃谨。
查了下文檔發(fā)現(xiàn)沙庐,OC的分類允許給分類添加屬性,但不會(huì)自動(dòng)生成getter佳吞、setter方法拱雏。有沒(méi)有解決方案呢?有底扳,通過(guò)運(yùn)行時(shí)建立關(guān)聯(lián)引用铸抑。
#import <UIKit/UIKit.h>
@interface UIViewController (ICEDemo)
@property (nonatomic, copy) NSString *str;
@end
#import "UIViewController+ICEDemo.h"
#import <objc/runtime.h>
static void *strKey = &strKey;
@implementation UIViewController (ICEDemo)
- (void)setStr:(NSString *)str {
objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
}
-(NSString *)str
{
return objc_getAssociatedObject(self, &strKey);
}
@end