美文网首页
问题:使用Runtime Associate 方法关联的对象,需

问题:使用Runtime Associate 方法关联的对象,需

作者: 姜小舟 | 来源:发表于2020-08-19 15:05 被阅读0次

    无论在MRC下还是ARC下均不需要,被关联的对象在生命周期内要比对象本身释放的晚很多,它们会在被 NSObject -dealloc 调用的object_dispose()方法中释放。

    关联对象的实现

    我们在 iOS 开发中经常需要使用分类(Category),为已经存在的类添加属性的需求,但是使用 @property 并不能在分类中正确创建实例变量和存取方法。

    不过,通过 Objective-C 运行时中的关联对象,也就是 Associated Object,我们可以实现上述需求。

    #import "DKObject+Category.h"
    #import <objc/runtime.h>
     
    @implementation DKObject (Category)
    
    - (void)setName:(NSString *)name {
        objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)name {
        // 隐式参数
        // _cmd == @selector(name)
        return objc_getAssociatedObject(self, _cmd);
    }
    @end
    

    我们使用了两个方法 objc_getAssociatedObject 以及 objc_setAssociatedObject来模拟『属性』的存取方法,而使用关联对象模拟实例变量。
    我们从三个 objc 运行时的方法为入口来对关联对象的实现一探究竟,其中两个方法是上一部分使用到的方法:

    NSLog(@"以键值对形式添加关联对象")
    void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
    NSLog(@"根据 key 获取关联对象")
    id objc_getAssociatedObject(id object, const void *key);
    NSLog(@"移除所有关联对象")
    void objc_removeAssociatedObjects(id object);
    

    在这里有必要解释两个问题:

    • 为什么向方法中传入 @selector(name)?
    • OBJC_ASSOCIATION_RETAIN_NONATOMIC 是干什么的?

    关于第一个问题,我们需要看一下这两个方法的原型:

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

    @selector(name) 也就是参数中的 key,其实可以使用静态指针 static void * 类型的参数来代替,不过在这里,笔者强烈推荐使用 @selector(name) 作为 key 传入。因为这种方法省略了声明参数的代码,并且能很好地保证 key 的唯一性。

    OBJC_ASSOCIATION_RETAIN_NONATOMIC 又是什么呢?

    typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
        OBJC_ASSOCIATION_ASSIGN = 0,  // 指定一个弱引用相关联的对象
        OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 指定相关对象的强引用,非原子性
        OBJC_ASSOCIATION_COPY_NONATOMIC = 3,  // 指定相关的对象被复制,非原子性
        OBJC_ASSOCIATION_RETAIN = 01401,  // 指定相关对象的强引用,原子性
        OBJC_ASSOCIATION_COPY = 01403     // 指定相关的对象被复制,原子性   
    };
    

    从这里的注释我们能看到很多东西,也就是说不同的 objc_AssociationPolicy 对应了不通的属性修饰符:

    objc_AssociationPolicy modifier
    OBJC_ASSOCIATION_ASSIGN assign
    OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic, strong
    OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic, copy
    OBJC_ASSOCIATION_RETAIN atomic, strong
    OBJC_ASSOCIATION_COPY atomic, copy

    相关文章

      网友评论

          本文标题:问题:使用Runtime Associate 方法关联的对象,需

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