Category-关联对象

本文详细介绍了Objective-C中Category无法直接添加成员变量的原因,并探讨了通过关联对象来模拟添加成员变量的方法,包括使用全局变量、字典以及关联对象API的实现方式。同时,解释了关联对象的内存管理和线程安全问题,以及其在分类中的应用。
摘要由CSDN通过智能技术生成

分类添加属性

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,就相当于是移除关联对象

关联之间的关系

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园建设方案旨在通过融合先进技术,如物联网、大数据、人工智能等,实现校园的智能化管理与服务。政策的推动和技术的成熟为智慧校园的发展提供了基础。该方案强调了数据的重要性,提出通过数据的整合、开放和共享,构建产学研资用联动的服务体系,以促进校园的精细化治理。 智慧校园的核心建设任务包括数据标准体系和应用标准体系的建设,以及信息化安全与等级保护的实施。方案提出了一站式服务大厅和移动校园的概念,通过整合校内外资源,实现资源共享平台和产教融合就业平台的建设。此外,校园大脑的构建是实现智慧校园的关键,它涉及到数据中心化、数据资产化和数据业务化,以数据驱动业务自动化和智能化。 技术应用方面,方案提出了物联网平台、5G网络、人工智能平台等新技术的融合应用,以打造多场景融合的智慧校园大脑。这包括智慧教室、智慧实验室、智慧图书馆、智慧党建等多领域的智能化应用,旨在提升教学、科研、管理和服务的效率和质量。 在实施层面,智慧校园建设需要统筹规划和分步实施,确保项目的可行性和有效性。方案提出了主题梳理、场景梳理和数据梳理的方法,以及现有技术支持和项目分级的考虑,以指导智慧校园的建设。 最后,智慧校园建设的成功依赖于开放、协同和融合的组织建设。通过战略咨询、分步实施、生态建设和短板补充,可以构建符合学校特色的生态链,实现智慧校园的长远发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值