美文网首页
分类中关联对象实现

分类中关联对象实现

作者: 春风依旧 | 来源:发表于2018-07-07 15:26 被阅读12次

    前言:

    分类中虽然不能直接添加成员变量,但是我们可以通过间接实现添加成员变量

    方法一:使用静态全局变量给分类添加属性

    static NSString *_name;
    -(void)setName:(NSString *)name
    {
        _name = name;
    }
    -(NSString *)name
    {
        return _name;
    }
    

           但是这样_name静态全局变量与类并没有关联,无论对象创建于销毁,只要程序在运行,_name变量就存在,并不是真正意义上的属性。

    方法二:使用Runtime动态添加属性

    Runtime提供了动态添加属性和获取属性的方法
    1、动态添加属性

    void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)
    
    参数一:id object : 给哪个对象添加属性,这里要给自己添加属性,用self。
    参数二:void * == id key : 属性名,根据key获取关联对象的属性的值,在objc_getAssociatedObject中通过次key获得属性的值并返回。
    参数三:id value : 关联的值,也就是set方法传入的值给属性去保存。
    参数四:objc_AssociationPolicy policy : 策略,属性以什么形式保存。
    
    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     // 指定相关的对象被复制,原子性   
    };
    

    2、获得属性

    objc_getAssociatedObject(id object, const void *key);
    参数一:id object : 获取哪个对象里面的关联的属性。
    参数二:void * == id key : 什么属性,与objc_setAssociatedObject中的key相对应,即通过key值取出value。
    

    3、移除所有关联对象

    - (void)removeAssociatedObjects
    {
        // 移除所有关联对象
        objc_removeAssociatedObjects(self);
    }
    person2.degree = nil;
    
    

           关联对象并不是存储在被关联对象本身内存中,而是存储在全局的统一的一个AssociationsManager中,如果设置关联对象为nil,就相当于是移除关联对象。

    关联对象的实际运用中的key

    static : 代表只能在此文件内访问
    1、赋值的key :static void *MyKey = &MyKey;

    static void *MyKey = &MyKey;
     // 关联对象
    objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
     // 获得关联对象
    objc_getAssociatedObject(obj, MyKey)
    

    2、内存地址的key : static char MyKey;

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

          const void * _Nonnull key: 仅仅是一个指针,&MyKey地址就可以, static char MyKey;不是一定要用char,这里只是它的字节是一个字节,在此仅仅只传一个指针而已

    3、使用属性名作为key : #define JKRevelKey @"revel";
            NSArray *str = @"revel";: 其实@"revel"就是自身的内存地址:唯一性,可以打印 str,内存地址是一样的

    objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    objc_getAssociatedObject(obj, @"property");
    

    4、使用get方法的@selecor作为key
    可以使用@selector(getter)来代替_cmd

    objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj, @selector(getter))
    

    关联对象的原理探索

    相关文章

      网友评论

          本文标题:分类中关联对象实现

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