iOS開發之Runtime關聯屬性

首先,推薦給你們一個很是好用的一個網站:

非盈利無廣告開發者專用網址導航:http://www.dev666.com/

API介紹

咱們先看看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參數說明:網站

  1. key:惟一鍵,在獲取值時經過該鍵獲取,一般是使用static const void *來聲明
  2. value:關聯所設置的值
  3. policy:內存管理策略,好比使用copy

獲取關聯值

若是咱們要獲取所關聯的值,須要經過key來獲取,調用以下函數:ui

id objc_getAssociatedObject(id object, const void *key)

object:與誰關聯,一般是傳self,在設置關聯時所指定的與哪一個對象關聯的那個對象參數說明:this

  1. 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:表示弱引用關聯,一般是基本數據類型,如intfloat,非線程安全咱們說明一下各個值的做用:spa

  1. OBJC_ASSOCIATION_RETAIN_NONATOMIC:表示強(strong)引用關聯對象,非線程安全
  2. OBJC_ASSOCIATION_COPY_NONATOMIC:表示關聯對象copy,非線程安全
  3. OBJC_ASSOCIATION_RETAIN:表示強(strong)引用關聯對象,是線程安全的
  4. OBJC_ASSOCIATION_COPY:表示關聯對象copy,是線程安全的

擴展屬性

咱們來寫一個例子,擴展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

 

非盈利無廣告開發者專用網址導航:http://www.dev666.com/

相關文章
相關標籤/搜索