日常开发中有时需要在对象中存放相关信息,通常做法是从要使用对象所属的类继承一个子类,然后改写子类,比如给子类添加额外的属性信息等。但是有时候类的实例是通过某种别的机制创建的,我们无法创建出自己所需要的子类。那么Objective-C中提供一种别的方法来解决这个问题,这就是“关联对象“。
可以为某对象关联许多其他对象,这些对象通过“键”来区分,储存对象值的时候可以指明“存储策略”,用以维护相关的内存语义。这些内存语义分别和属性中定义的相对应。 (objc_AssociationPolicy)
关联类型 | 等效的@property |
---|---|
OBJC_ASSOCIATION_ASSIGN | assign |
OBJC_ASSOCIATION_RETAIN_NONATOMIC | nonatomic,retain |
OBJC_ASSOCIATION_COPY_NONATOMIC | nonatiomic,copy |
OBJC_ASSOCIATION_RETAIN | retain |
OBJC_ASSOCIATION_COPY | copy |
关联对象相关方法
-
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy)
此方法用于通过使用给定的键和策略为某对象设置关联对象值。 -
id objc_getAssociatedObject(id object, void *key)
通过给定键从某对象中获取对应的关联对象值。 -
void objc_removeAssociatedObjects(id object)
移除指定对象中的全部关联对象。
在关联对象中,如果想要两个键匹配同一个值,则二者必须是完全相同的指针。因此在设置关联对象的时候,都是通过使用静态全局变量作为键
使用举例
例如在iOS中我们都是用过UIAlert类,当用户要处理点击事件的时候,需要通过委托协议来实现。这时候就需要把视图和事先动作的代码分开。例如:
-(void)userAlert {
UIAlert *alert = [[UIAlert alloc] initWithTitle:@"Alert"
message:@"do you want to close?"
delegate: self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK",nil];
[alert show];
}
#param -mark UIAlertView Delegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger:)buttonIndex{
if(buttonIndex == 0){
//do action
} else {
//do action
}
}
通常都是这么做,但是如果代码中使用多个UIAlerView的时候,还需要通过在回调中判断alertView
的类型,然后再去处理响应的逻辑。要是能够是创建视图的时候,就把每个按钮响应的逻辑写好,那就简单多了。于是可以:
_alertView = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"This is deprecated?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Ok", nil];
void (^block)(NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == 0) {
[self doCancel];
} else {
[self doOk];
}
};
objc_setAssociatedObject(self.alertView, MyAlertViewKey, block, OBJC_ASSOCIATION_COPY);
#pragma -mark UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, MyAlertViewKey);
block(buttonIndex);
}
网友评论