美文网首页
第10条:在既有类中使用关联对象存放自定义数据

第10条:在既有类中使用关联对象存放自定义数据

作者: MrSYLong | 来源:发表于2018-08-12 14:41 被阅读4次

“关联对象”:可以给某个对象关联许多其他对象,这些对象通过“键”来区分。
存储对象值时,可以指明“存储策略”,用以维护相应的“内存管理语义”。
存储策略由名为objc_AssociationPolicy的枚举所定义:

对象关联类型.jpg

使用方法:

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

此方法以给定的键和策略为某对象设置关联对象值。

id objc_getAssociatedObject(id object, void*key)

此方法根据给定的键从某对象中获取相应的关联对象值。

void objc_removeAssociatedObjects(id object)

此方法移除指定对象的全部关联对象。

注意事项:
设置关联对象时用的键(key)是个“不透明的指针”,在设置关联对象值时,通常使用静态全局变量做键。

// 示例1
#import "EOCPerson.h"
#import <objc/runtime.h>

static void *kAssociatedObject = @"associatedObject";

EOCPerson *person = [EOCPerson new];
objc_setAssociatedObject(person, kAssociatedObject, @"hello", OBJC_ASSOCIATION_COPY_NONATOMIC);

NSString *associatedStr = objc_getAssociatedObject(person, kAssociatedObject);
NSLog(@"associatedStr :  %@",associatedStr);

objc_removeAssociatedObjects(person);
associatedStr = objc_getAssociatedObject(person, kAssociatedObject);
NSLog(@"associatedStr :  %@",associatedStr);

输出:
2018-08-12 12:57:26.695315+0800 Demo[28077:1457259] associatedStr :  hello
2018-08-12 12:57:32.307315+0800 Demo[28077:1457259] associatedStr :  (null)
// 示例2
static void *EOCMyAlertViewKey = @"EOCMyAlertViewKey";

- (void)askUserAQuestion
{
    UIAlertView *alert = [[UIAlertView alloc] 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, OBJC_ASSOCIATION_COPY);
    
    [alert show];
}

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

注意:示例中块可能会捕获某些变量,这也许会造成“保留环”(就是循环引用)。

只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于查找的bug。

相关文章

网友评论

      本文标题:第10条:在既有类中使用关联对象存放自定义数据

      本文链接:https://www.haomeiwen.com/subject/hyusbftx.html