在既有类中使用关联对象存放自定义数据;有时候需要在对象中存放相关信息。这时我们通常会从对象的所属的类中继承一个子类,然后改用这个子类对象。然而并非所有情况下都能这么做,有时候类的实例可能是由某种机制所创建的,而开发者,无法令这种机制创建出自己所写的子类实例。 OC 中有一项强大的特性可以解决此问题,这就是“关联对象”(Associate Object)。
关联对象类型(policy):
关联对象方法:
// ⬇️此方法以给定的键 和策略 为某对象设置关联对象值:
void objc_setAssociateObject(id *object, void *key, id value, objc_AssociationPolicy policy);
// ⬇️根据指定的键从某对象中获取相应的关联对象值:
void objc_getAssociateObject(id object, void *key);
// ⬇️移除指定对象的全部关联值:
void objc_reomoveAssociatedObjects(id object);
⚠️我们可以把某对象想象成 NSDictionary, 把关联对象的值理解为字典中的条目,于是,存取关联对象的值就相当于给字典赋值、取值;然而两者之间有个很重要的差别是:设置关联对象时用的键是个“不透明的指针”(opaque pointer),在设置关联对象时,若想令两个键匹配到同一个值,则二者必须是完全相同的指针才行,鉴于此,在设置关联对象值时,通常使用静态全局变量作为 键。
#import <objc/runtime>
@interface ViewController ()<UIAlertViewDelegate>
@end
static void *EOCAlertViewKey = "AlertViewKey";
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"This is title" message:@"This is message" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ok", nil];
alert.delegate = self;
void (^alertHandlerBlock)(NSInteger) = ^(NSInteger index) {
NSLog(@"%@", @(index));
};
objc_setAssociatedObject(alert, EOCAlertViewKey, alertHandlerBlock, OBJC_ASSOCIATION_COPY);
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
void(^alertHandlerBlock)(NSInteger) = objc_getAssociatedObject(alertView, EOCAlertViewKey);
alertHandlerBlock(buttonIndex);
}
@end