runtime关联属性示例

前言

在开发中经常需要给已有的类添加方法和属性,但是Objective-C是不允许给已有类通过分类添加属性的,因为类分类是不会自动生成成员变量的。但是,我们可以通过运行时机制就可以做到了。

本篇文章适合新手阅读,手把手教你如何在项目中使用关联属性!

API介绍

我们先看看Runtime提供的关联API,只有这三个API,使用也是非常简单的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

/**

* 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函数,这个函数的功能是移除指定的对象上所有的关联。既然我们要添加关联属性,几乎不会存在需要手动取消关联的场合。

设置关联值(Setter)

对于设置关联,我们需要使用下面的API关联起来:

1

2

3

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

参数说明:

  • object:与谁关联,通常是传self
  • key:唯一键,在获取值时通过该键获取,通常是使用static const void *来声明
  • value:关联所设置的值
  • policy:内存管理策略,比如使用copy

获取关联值(Getter)

如果我们要获取所关联的值,需要通过key来获取,调用如下函数:

1

2

3

id objc_getAssociatedObject(id object, const void *key)

参数说明:

  • object:与谁关联,通常是传self,在设置关联时所指定的与哪个对象关联的那个对象
  • key:唯一键,在设置关联时所指定的键

关联策略

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

/**

* 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,非线程安全
  • OBJC_ASSOCIATION_RETAIN_NONATOMIC:表示强(strong)引用关联对象,非线程安全
  • OBJC_ASSOCIATION_COPY_NONATOMIC:表示关联对象copy,非线程安全
  • OBJC_ASSOCIATION_RETAIN:表示强(strong)引用关联对象,是线程安全的
  • OBJC_ASSOCIATION_COPY:表示关联对象copy,是线程安全的

扩展属性

我们来写一个例子,扩展UIControl添加Block版本的TouchUpInside事件。

扩展头文件声明:

1

2

3

4

5

6

7

8

9

10

11

#import <UIKit/UIKit.h>

typedef void (^HYBTouchUpBlock)(id sender);

@interface UIControl (HYBBlock)

@property (nonatomic, copy) HYBTouchUpBlock hyb_touchUpBlock;

@end

扩展实现文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

#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

时间: 2025-01-12 04:30:22

runtime关联属性示例的相关文章

EF自动生成的(T4模板) 关联属性元数据修改

为了实现 T4模板关联属性 不要序列化的问题 就是要在具体的 关联属性上面添加一个元数据 这里利用以前的 Newtonsoft.Json 这个框架为例 效果应该为 就是要在关联属性上面添加元数据  [JsonIgnore] 注意: 默认会报错,如下 请记住错误个数,多了就证明你写的有问题.而且你不要奇怪有这么多错误. 如果你不出现这么多个错误提示,你就应该去找一下模板 如下的位置. 步骤 1.导入命名空间.不然出来的全是BUG //添加引用public string UsingDirective

CSS3 变形、过渡、动画、关联属性浅析(转载)

一.变形 transform:可以对元素对象进行旋转rotate.缩放scale.移动translate.倾斜skew.矩阵变形matrix.示例: transform: rotate(90deg) scale(1.5,0.8) translate(100px,50px) skew(45deg,45deg); /*矩阵变形*/ matrix(<number>,<number>,<number>,<number>,<number>,<numb

CSS3变形、过渡、动画、关联属性浅析

一.变形 transform:可以对元素对象进行旋转rotate.缩放scale.移动translate.倾斜skew.矩阵变形matrix.示例: transform: rotate(90deg) scale(1.5,0.8) translate(100px,50px) skew(45deg,45deg); /*矩阵变形*/ matrix(<number>,<number>,<number>,<number>,<number>,<numb

【iOS】关联属性存取数据

有时候我们需要在现有的类存放一些额外的信息,通常的做法是继承一个子类,然后定义新增加的属性,然而如果我们为每个需要的类都添加一个类显得太麻烦了,objc提供了一个关联属性的特性,可以给一个对象关联一个属性(做过.NET的朋友一定熟悉附加属性,objc的关联属性与.NET的附加属性有点类似类似) 使用关联属性很简单,下面是几个主要的函数 //设置关联属性 objc_setAssociatedObject(id object, const void *key, id value, objc_Asso

grid 布局 属性示例

<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible"

Supermap iserver client 空间查询关联属性过滤示例

点查询并根据属性条件过滤示例代码 //关联外表 var joinItem=new SuperMap.REST.JoinItem({ foreignTableName: "V_REGION_LAND", joinFilter: "BBS_PARCEL.CADASTRALNO = V_REGION_LAND.CADASTRALNO ", joinType: "INNERJOIN" }); var queryParam, queryByGeometry

iOS runtime 关联对象(Associated Object)

?需求 同一个类有多个alertView, 不同的alertView 点击确定按钮 执行的方法不同 alertOne 点击 确定按钮 执行 methodOne, alertTwo 点击确定按钮 执行 methodTwo 常规做法 初始化并显示 alertOne - (IBAction)showAlertOne:(id)sender {     UIAlertView *alertOne = [[UIAlertView alloc]initWithTitle:@"AlertOne" me

objc runtime之属性扩展(objc_getAssociatedObject,objc_setAssociatedObject,objc_removeAssociatedObjects)

category与associative作为objective-c的扩展机制的两个特性,category即类型,可以通过它来扩展方 法:associative,可以通过它来扩展属性:在iOS开发中,可能category比较常见,相对的associative,就用的比较少,要用 它必须使用<objc/runtime.h>的头文件,然后就可以自由使用objc_getAssociatedObject以及 objc_setAssociatedObject,我们来看下这两个方法: 1.创建关联:参数设置

使用runtime获取属性

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #3495af } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000; min-height: 15.0px } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000 }