咱們先看看Runtime提供的關聯API,只有這三個API,使用也是很是簡單的:安全
/** * 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 */ void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) /** * 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 */ id objc_getAssociatedObject(id object, const void *key) /** * 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 */ void objc_removeAssociatedObjects(id object)
實際上,咱們幾乎不會使用到objc_removeAssociatedObjects
函數,這個函數的功能是移除指定的對象上全部的關聯。既然咱們要添加關聯屬性,幾乎不會存在須要手動取消關聯的場合。ide
對於設置關聯,咱們須要使用下面的API關聯起來:函數
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
object
:與誰關聯,一般是傳self
參數說明:網站
key
:惟一鍵,在獲取值時經過該鍵獲取,一般是使用static const void *
來聲明value
:關聯所設置的值policy
:內存管理策略,好比使用copy
若是咱們要獲取所關聯的值,須要經過key
來獲取,調用以下函數:ui
id objc_getAssociatedObject(id object, const void *key)
object
:與誰關聯,一般是傳self
,在設置關聯時所指定的與哪一個對象關聯的那個對象參數說明:this
key
:惟一鍵,在設置關聯時所指定的鍵咱們先看看設置關聯時所指定的policy
,它是一個枚舉類型,看官方說明:atom
/** * Policies related to associative references. * These are options to objc_setAssociatedObject() */ typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) { OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */ OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. * The association is not made atomically. */ OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied. * The association is not made atomically. */ OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object. * The association is made atomically. */ OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied. * The association is made atomically. */ };
OBJC_ASSOCIATION_ASSIGN:表示弱引用關聯,一般是基本數據類型,如int
、float
,非線程安全咱們說明一下各個值的做用:spa
咱們來寫一個例子,擴展UIControl
添加Block版本的TouchUpInside
事件。線程
擴展頭文件聲明:code
#import <UIKit/UIKit.h> typedef void (^HYBTouchUpBlock)(id sender); @interface UIControl (HYBBlock) @property (nonatomic, copy) HYBTouchUpBlock hyb_touchUpBlock; @end
擴展實現文件:
#import "UIControl+HYBBlock.h" #import <objc/runtime.h> static const void *sHYBUIControlTouchUpEventBlockKey = "sHYBUIControlTouchUpEventBlockKey"; @implementation UIControl (HYBBlock) - (void)setHyb_touchUpBlock:(HYBTouchUpBlock)hyb_touchUpBlock { objc_setAssociatedObject(self, sHYBUIControlTouchUpEventBlockKey, hyb_touchUpBlock, OBJC_ASSOCIATION_COPY); [self removeTarget:self action:@selector(hybOnTouchUp:) forControlEvents:UIControlEventTouchUpInside]; if (hyb_touchUpBlock) { [self addTarget:self action:@selector(hybOnTouchUp:) forControlEvents:UIControlEventTouchUpInside]; } } - (HYBTouchUpBlock)hyb_touchUpBlock { return objc_getAssociatedObject(self, sHYBUIControlTouchUpEventBlockKey); } - (void)hybOnTouchUp:(UIButton *)sender { HYBTouchUpBlock touchUp = self.hyb_touchUpBlock; if (touchUp) { touchUp(sender); } } @end