Associated Objects 小记

天线视频

天线视频

发表于 2017-06-05 09:10:28

在一个 viewController 的生命周期内,只执行一次某段代码,怎么做?

第一种方法是最常见也是最简单的方法,加标记位。

还有没有更优雅的办法呢?面向 Google 编程,得到这个答案:

void (^excuteOnce)() = ^{  
    if (objc_getAssociatedObject(self, _cmd)) {
        return;
    }

    objc_setAssociatedObject(self, _cmd, @"Launched", OBJC_ASSOCIATION_RETAIN);
    // some code
};
excuteOnce();

什么是 Associated Objects

OC 有一个最大的弊端就是,我们可以通过 Category 给一个现有的类添加属性,但不能添加实例变量。不过还好有 runtime ,我们可以通过 Associated Objects 达到这一目的。

通过查看 <objc/runtime.h> 发现, 有三个相关的函数:

  • objc setAssociatedObject(id object, const void *key, id value, objc AssociationPolicy policy)

    用于给对象添加关联对象,传入 nil 则可以移除已有的关联对象;

  • objc_getAssociatedObject(id object, const void *key)

    用于获取关联对象;

  • objc_removeAssociatedObjects(id object)

    用于移除一个对象的所有关联对象。

Tips: 一般情况下最好不要用 objc_removeAssociatedObjects 这个函数,它会移除掉一个对象所有的关联对象。所以当我们只想移除某一个关联对象的时候,更好的方法应该是,通过 objc_setAssociatedObject 将它设置为 nil。

关联策略

Behavior @property Equivalent Description
OBJC_ASSOCIATION_ASSIGN @property (assign) @property (unsafe_unretained) 指定一个关联对象的弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC @property (nonatomic, strong) 指定一个关联对象的强引用,不能被原子化使用
OBJC_ASSOCIATION_COPY_NONATOMIC @property (nonatomic, copy) 指定一个关联对象的copy引用,不能被原子化使用
OBJC_ASSOCIATION_RETAIN @property (atomic, strong) 指定一个关联对象的强引用,能被原子化使用
OBJC_ASSOCIATION_COPY @property (atomic, copy) 指定一个关联对象的copy引用,能被原子化使用

使用场景

根据 Mattt Thompson 大神的总结, Associated Objects 比较好的使用场景有这三种:

  • 添加私有属性用于更好地去实现细节。当扩展一个内建类的行为时,保持附加属性的状态可能非常必要。注意以下说的是一种非常教科书式的关联对象的用例:AFNetworking在 UIImageView 的category上用了关联对象来保持一个operation对象,用于从网络上某URL异步地获取一张图片。

  • 添加public属性来增强category的功能。有些情况下这种(通过关联对象)让category行为更灵活的做法比在用一个带变量的方法来实现更有意义。在这些情况下,可以用关联对象实现一个一个对外开放的属性。回到上个AFNetworking的例子中的 UIImageView category,它的 imageResponseSerializer方法允许图片通过一个滤镜来显示、或在缓存到硬盘之前改变图片的内容。

  • 创建一个用于KVO的关联观察者。当在一个category的实现中使用KVO时,建议用一个自定义的关联对象而不是该对象本身作观察者。ng an associated observer for KVO**. When using KVO in a category implementation, it is recommended that a custom associated-object be used as an observer, rather than the object observing itself.

参考链接

Objective-C Associated Objects 的实现原理 Associated Objects

相关帖子
用户评论
开源开发学习小组列表