Objective-C Associative-References(关联引用)

Associative-References 的使用

需求

有时需要在对象中存放相关信息,我们通常使用对象的所属类继承一个子类,然后改用,这个对象的子类。但并非所有对象都能这么做,比如类簇(Class Clusters),是不建议被继承的。那么这个时候就可以利用关联引用(Associative-References)解决此问题。

API

1
2
3
4
5
6
7
8

#import <objc/runtime.h>
//设置关联
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)
//获取关联对象
id objc_getAssociatedObject(id object, void *key)
//移除关联
void objc_removeAssociatedObjects(id object)
参数 说明
object 被关联的对象
key 关联的key
value 关联的key对应的对象
policy 内存管理策略
objc_AssociationPolicy枚举 对应的@property修饰符
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic,retain
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic,copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_COPY copy

有别于NSDictionary,关联引用中,想让两个key匹配到同一个value,必须两个key的指针完全相等才行。所以key通常使用静态全局变量

举个🌰

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

#import <objc/runtime.h>

static void *EOCMyAlertViewKey = "EOCMyAlertViewKey";

- (void)askUserAQuestion {
UIAlertView *alert = [[UIAlertViewalloc]
initWithTitle:@"Question"
message:@"What do you want to do?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Continue", nil];

void (^block)(NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == 0) {
[self doCancel];
} else {
[self doContinue];
}
};

objc_setAssociatedObject(alert,
EOCMyAlertViewKey,
block,
BJC_ASSOCIATION_COPY);

[alert show];
}

// UIAlertViewDelegate protocol method
- (void)alertView:(UIAlertView*)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex
{
void (^block)(NSInteger) =
objc_getAssociatedObject(alertView, EOCMyAlertViewKey);
block(buttonIndex);
}