iOS开发之Runtime关联属性

原创
2016/09/23 11:13
阅读数 1.2K

首先,推荐给大家一个非常好用的一个网站:

非盈利无广告开发者专用网址导航: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函数,这个函数的功能是移除指定的对象上所有的关联。既然我们要添加关联属性,几乎不会存在需要手动取消关联的场合。

对于设置关联,我们需要使用下面的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来获取,调用如下函数:

id objc_getAssociatedObject(id object, const void *key)

object:与谁关联,通常是传self,在设置关联时所指定的与哪个对象关联的那个对象参数说明:

  1. key:唯一键,在设置关联时所指定的键

关联策略

我们先看看设置关联时所指定的policy,它是一个枚举类型,看官方说明:

/**

* 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,非线程安全我们说明一下各个值的作用:

  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事件。

扩展头文件声明:

#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/

 

 

展开阅读全文
打赏
0
9 收藏
分享
加载中
更多评论
打赏
0 评论
9 收藏
0
分享
返回顶部
顶部