2. 定义关联对象时,可指定内存管理语义,用以模仿定义属性时所采用的“拥有关系”和“非拥有关系”。
3. 只有再其他做法不可行时才应选择关联对象,因为这种做法通常会引入难以查找的bug。
有时候类的实例可能是某种机制所创建,而开发者无法令这种机制创建出自己所写的子类实例。
可以给某对象关联许多其他对象。这些对象会通过“键”来区分。
存储对象值的时候,可以指明“存储策略”,用以维护相应的“内存管理语义”。
存储策略由名为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 |
以下方法用来管理关联对象:
① void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy);
此方法以给定的键和策略为某对象设置关联对象值。
② void objc_getAssociatedObject(id object, void *key);
此方法根据给定的键从某对象中获取相应的关联对象值。
③ void objc_removeAssociatedObjects(id object);
此方法移除指定对象的全部关联对象。
4. 设置关联对象用的键是个“不透明的指针”,即所指向的数据结构不局限于某种特定类型的指针。
再设置关联对象值时,若想令两个键匹配到同一个值,则二者必须时完全相同的指针才行。
跟NSDictionary不一样。NSDictionary认为“isEqual:”返回YES,则二者相同。
故设置关联对象值时,通常使用静态全局变量做键。
5.例子:
static void *MyAlertViewKey = “MyAlertViewKey”; - (void) askUserQuestion { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@“Question” message:@“What?” delegate:self cancelButtonTitle:@“cancel” otherButtonTitles:@“Continue”,nil]; void (^block)(NSInteger) = ^(NSInteger buttonIndex){ if(buttonIndex == 0){ [self doCancel]; } else { [self doContinue]; } }; objc_setAssociatedObject(alert, MyAlertViewKey, block, BJC_ASSOCIATION_COPY); [alert show]; } - (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { void (^block)(NSInteger) = objc_getAssociatedObject (alertView, MyAlertViewKey); block(buttonIndex); }
Effective Objective-C 2.0 编写高质量iOS与OS X代码 在既有类中使用关联对象存放自定义数据,布布扣,bubuko.com
Effective Objective-C 2.0 编写高质量iOS与OS X代码 在既有类中使用关联对象存放自定义数据