美文网首页IOS开发
Category-关联对象

Category-关联对象

作者: 越天高 | 来源:发表于2020-10-22 11:38 被阅读0次

分类添加属性

struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;

    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) return classMethods;
        else return instanceMethods;
    }

    property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
    
    protocol_list_t *protocolsForMeta(bool isMeta) {
        if (isMeta) return nullptr;
        else return protocols;
    }
};

Category能否添加成员变量?如果可以,如何给Category添加成员变量?
不能直接给Category添加成员变量,但是可以使用关联对象,间接实现Category有成员变量的效果

如果我们给类添加一个属性,如下代码

@property (nonatomic, assign)  int age;

相当于做了三件事,1,创建_age成员变量;2.生成设方法和get方法的声明;3.生成这两个方法的具体实现。
如果我们在分类中添加属性,1他只会做生成方法的声明
我们可以思考 我们是不是可以自己去实现,我们自己去写分类的set和get方法的实现,发现他编译会报错Instance variables may not be placed in categories
如果我们在分类增加属性,其实也就是想以后想普通的成员变量一样使用,p.age 方式来取值和设置值
我们之前可以用.age去值是因为,我们设置的时候,将10赋给了_age这个成员变量,

02使用字典完善数组

可以在set方法的时候用一个全局变量,将值存放起来,但是全局变量有个缺陷,如果我们创建多个person对象,他们就是共用这个变量,导致数据混乱。
可以使用一个字典,来实现每一个peroson对象,对应自己的那个变量

NSMutableDictionary *weight_;
+ (void)load
{
    weight_ = [NSMutableDictionary dictionary];
}
- (void)setAge:(int)age
{
    NSString *key = [NSString stringWithFormat:@"%p", self];
    weight_[key] = @(age);
}
- (int)age
{
    NSString *key = [NSString stringWithFormat:@"%p", self];
    return [weight_[key] intValue];
}

3使用字典存在的问题

成员变量的10是在person对象的内存结构中的,我们设置的age他会存在于全局字典对象里面,他会一值在内存中,存在线程安全问题,假如不同线程里面的person对象都要访问这个属性,就会造成多个线程共同访问一个对象
如若我们想增加一个属性,还要在增加一个字典对象。开发工程中我们一般不采用这种方式,

04关联对象的基本使用

利用关联对象来实现给分类添加属性,利用runtime的函数来实现
关联对象提供了以下API


    添加关联对象
/**
object:给哪个对象关联
key:关联的key
value:关联的对象
policy:内存策略
*/
    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)

关联策略


截屏2020-10-22 上午10.41.33.png
const void *Namekey = &Namekey;
- (void)setName:(NSString *)name
{
    objc_setAssociatedObject(self, Namekey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
   return  objc_getAssociatedObject(self, Namekey);
}

key的用法


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

static char MyKey;//   因为我们主要用他的地址,所以我们用个内存比较小的类型。
objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, &MyKey)

使用属性名作为key//这种直接写出来字符串,他是存在常量区的,无论写多少遍他都是同一个对象。
objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(obj, @"property");

使用get方法的@selecor作为key//简单编译器提示,
objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))

用全局变量做key的话存在问题,别人可以拿到并可以改里面的值,我们本意是不希望别人访问这个key,可以在前面加上static像第一种做饭

extern const void *NameKey;

06答疑

给类对象关联属性,把id给成类对象关联就可以,
分类的结构决定了 它不能添加成员变量,他没有存放成员变量的属性,

分类不能直接添加成员变量的,原来的类有个ivars来存放成员变量的,关联对象不是把这个对象当成成员变量,放到这个ivars数组里面的,他不会影响来的类对象和实例对象的结构

07底层的数据结构

实现关联对象技术的核心对象有

AssociationsManager->
AssociationsHashMap //字典->
ObjectAssociationMap->
ObjcAssociation->策略和值

objc_setAssociatedObject->_object_set_associative_reference


源码结构图

08底层数据结构

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

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


关联之间的关系

内存策略里并没有弱引用,

对象释放这个关联对象是不是被移除
肯定被移除

相关文章

  • Category-关联对象

    分类添加属性 Category能否添加成员变量?如果可以,如何给Category添加成员变量?不能直接给Categ...

  • Swift 为分类增加属性objc_getAssociated

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

  • iOS runtime关联对象 objc_setAssociat

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

  • 关联对象

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

  • 关联对象

    关联对象原理 关联对象并不是存储在被关联对象本身内存中,关联对象存储在全局的统一的一个AssociationsMa...

  • iOS 关联对象

    概述 关联对象顾名思义,就是给对象关联对象的意思,一个对象可以关联多个其他对象,这些对象通过key来区分,存储对象...

  • 关联对象

    关联对象会用被关联对象作为key,将关联对象存储到全局的哈希表里。 AssociationHashMap Asso...

  • iOS关联对象技术原理

    iOS关联对象技术原理 iOS关联对象技术原理

  • 关联对象

    分类里面添加成员变量, 分类里面是不能直接添加成员变量的,但是可以通过runtime间接添加成员变量。 为什么...

  • 关联对象

    能否为分类添加 “成员变量” ? 为分类所添加的成员变量添加在哪里? 所有对象的关联内容都在同一个全局容器内关联对...

网友评论

    本文标题:Category-关联对象

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