美文网首页
关联对象总结

关联对象总结

作者: 斑驳的流年无法释怀 | 来源:发表于2018-08-18 12:23 被阅读10次

默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。但可以通过关联对象来间接实现

关联对象提供了以下API

添加关联对象

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

获得关联对象

id objc_getAssociatedObject(id object, const void * key)

移除所有的关联对象

void objc_removeAssociatedObjects(id object)

key的常见用法

  1. static void *MyKey = &MyKey;
    objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj, MyKey)

  2. static char MyKey;
    objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj, &MyKey)

  3. 使用属性名作为key
    objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    objc_getAssociatedObject(obj, @"property");

  4. 使用get方法的@selecor作为key
    objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj, @selector(getter))

示例:

- (void)setName:(NSString *)name
{
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)name
{
    // 隐式参数
    // _cmd == @selector(name)
    return objc_getAssociatedObject(self, _cmd);
}

objc_AssociationPolicy

image.png

关联对象的原理

实现关联对象技术的核心对象有
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation

objc4源码解读:objc-references.mm

image.png image.png
void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) {
    // retain the new value (if any) outside the lock.
    ObjcAssociation old_association(0, nil);
    id new_value = value ? acquireValue(value, policy) : nil;
    {
        AssociationsManager manager;
        AssociationsHashMap &associations(manager.associations());
        disguised_ptr_t disguised_object = DISGUISE(object);
        if (new_value) {
            // break any existing association.
            AssociationsHashMap::iterator i = associations.find(disguised_object);
            if (i != associations.end()) {
                // secondary table exists
                ObjectAssociationMap *refs = i->second;
                ObjectAssociationMap::iterator j = refs->find(key);
                if (j != refs->end()) {
                    old_association = j->second;
                    j->second = ObjcAssociation(policy, new_value);
                } else {
                    (*refs)[key] = ObjcAssociation(policy, new_value);
                }
            } else {
                // create the new association (first time).
                ObjectAssociationMap *refs = new ObjectAssociationMap;
                associations[disguised_object] = refs;
                (*refs)[key] = ObjcAssociation(policy, new_value);
                object->setHasAssociatedObjects();
            }
        } else {
            // setting the association to nil breaks the association.
            AssociationsHashMap::iterator i = associations.find(disguised_object);
            if (i !=  associations.end()) {
                ObjectAssociationMap *refs = i->second;
                ObjectAssociationMap::iterator j = refs->find(key);
                if (j != refs->end()) {
                    old_association = j->second;
                    refs->erase(j);
                }
            }
        }
    }
    // release the old value (outside of the lock).
    if (old_association.hasValue()) ReleaseValue()(old_association);
}


class AssociationsManager {
    // associative references: object pointer -> PtrPtrHashMap.
    static AssociationsHashMap *_map;
public:
    AssociationsManager()   { AssociationsManagerLock.lock(); }
    ~AssociationsManager()  { AssociationsManagerLock.unlock(); }
    
    AssociationsHashMap &associations() {
        if (_map == NULL)
            _map = new AssociationsHashMap();
        return *_map;
    }
};

注意

  1. 关联对象不会强引用对象,而是保存了对象的值给了一个新的对象
  2. 关联对象没有弱引用的效果,使用时需要注意

相关文章

  • iOS底层原理总结 - 关联对象实现原理

    iOS底层原理总结 - 关联对象实现原理 iOS底层原理总结 - 关联对象实现原理

  • 关联对象总结

    默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。但可以通过关联对象来间接实现 关联对象提供了以下AP...

  • Objective-C 语言特性之关联变量

    关联变量相关总结。 一 :关联变量操作方法 (1)添加关联对象 void objc_setAssociatedOb...

  • NSRuntime使用篇

    使用总结runtime开源代码 对象的关联: 设置关联值 void objc_setAssociatedObjec...

  • 探寻block的本质

    转自:探寻block的本质拓展:探寻OC对象的本质iOS底层原理总结 - 关联对象实现原理iOS底层原理总结 - ...

  • 2018-04-21

    第11章:持有对象 直接总结 1、数组将数字与对象关联起来 2、Collection保存单一元素,Map保存相关联...

  • 中介者模式(mediator)

    一句话总结 星状结构 内容 由对象直接耦合变成对象和中介者进行关联,中介者在于其他对象进行关联,将网状结构变成星状...

  • Swift 为分类增加属性objc_getAssociated

    OC 获取关联对象 Swift 获取关联对象——错误的写法 Swift 获取关联对象——正确的写法 设置关联对象 ...

  • iOS runtime关联对象 objc_setAssociat

    关联对象的作用: 关联对象可以给某个对象关联一个或者多个其他对象,这些对象通过健来区分。 创建存储关联对象objc...

  • 关联对象

    关联对象的方式 关联对象源码基本思路 关联对象的结构:AssociationsHashManager // Ass...

网友评论

      本文标题:关联对象总结

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