OC底层知识(五) :关联对象

简介: OC底层知识(五) :关联对象

上一篇博客里面写到如何实现给分类添加成员变量?,在这里咱们通过学习关联对象来解决下。


一、关联对象的常用API


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


void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)
  • 上面方法的参数解释


/** 关联对象的参数
    @param object 设置对象: 在这里是 self(类自己)
    @param key#> <#key#> description#>
    @param value#> 关联值:这里是 name
    @param policy#> 关联策略
    @return
*/
 /**  关联策略(objc_AssociationPolicy)                     对应的修饰符
    OBJC_ASSOCIATION_ASSIGN = 0,                          assign
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1                 strong, nonatomic
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,                  copy, nonatomic
    OBJC_ASSOCIATION_RETAIN = 01401,                      strong, atomic
    OBJC_ASSOCIATION_COPY = 01403                         copy, atomic
  */
  • 获得关联对象


id objc_getAssociatedObject(id object, const void * key)
  • 移除所有的关联对象


void objc_removeAssociatedObjects(id object)


二、关联对象的实际运用中的Key


static : 代表只能在此文件内访问

说明添加几个成员变量就要写几个关联对象的Key


下面四种关联对象的实际使用的demo


  • 2.1、赋值的key :static void *MyKey = &MyKey;
static void *MyKey = &MyKey;
 // 关联对象
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
 // 获得关联对象
objc_getAssociatedObject(obj, MyKey)
  • demo查看JKPerson+Test
  • 2.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,这里只是它的字节是一个字节,在此仅仅只传一个指针而已
    demo查看JKPerson+Test2


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


objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(obj, @"property");
  • demo查看JKPerson+Test3
  • 2.4、使用get方法的@selecor作为key
    可以使用_cmd来代替@selector(getter)


objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))
  • demo查看JKPerson+Test4


三、关联对象的原理探索


  • 3.1、实现关联对象技术的核心对象有
    AssociationsManager


Class  AssociationsManager {
   static AssociationsHashMap *_map;
};
  • AssociationsHashMap


class AssociationsHashMap : public unordered_map<disguised_ptr_t, ObjectAssociationMap *, DisguisedPointerHash, DisguisedPointerEqual, AssociationsHashMapAllocator>
  • ObjectAssociationMap


class ObjectAssociationMap : public std::map<void *, ObjcAssociation, ObjectPointerLess, ObjectAssociationMapAllocator>
  • ObjcAssociation


class ObjcAssociation {
   uintptr_t _policy;
   id _value;
}


  • 3.2、下面图表述了上面四个核心对象的关系


image.png


3.3、移除关联对象移除所有的关联对象


  • 移除关联对象


person2.degree = nil;
  • 移除所有的关联对象


void objc_removeAssociatedObjects(id object)
  • 可以查看demo里面的ViewController中的test5方法:当object 被移除的同时对应上面的AssociationsHashMap也会被对应的移除,字典(看到Map可以当做字典来看待)是一对一的关系。
目录
相关文章
|
索引
07-OC底层原理之类的加载流程
07-OC底层原理之类的加载流程
37 0
|
API
OC底层知识(三): KVC
OC底层知识(三): KVC
185 0
OC底层知识(三): KVC
|
C语言 iOS开发
OC 底层知识(二): KVO
OC 底层知识(二): KVO
188 0
OC 底层知识(二): KVO
|
存储 iOS开发 C++
OC 底层知识(一):OC的本质
OC 底层知识(一):OC的本质
247 0
OC 底层知识(一):OC的本质
|
Android开发 iOS开发
OC:跟随码哥一起学习KVO
KVO的全称 Key-Value Observing,俗称“键值监听”,可以用于监听某个对象属性值的改变。本文将带你全面了解KVO实现、原理、底层逻辑,以及相关拓展
188 0
OC:跟随码哥一起学习KVO
|
存储 安全 编译器
OC底层知识(十二) : 内存管理
OC底层知识(十二) : 内存管理
195 0
OC底层知识(十二) : 内存管理
|
安全 Unix 程序员
OC底层知识(十一) : 多线程
OC底层知识(十一) : 多线程
199 0
OC底层知识(十一) : 多线程
|
监控 API iOS开发
OC底层知识(十) : RunLoop
OC底层知识(十) : RunLoop
305 0
OC底层知识(十) : RunLoop
C#(二十五)之C#对象比较
本篇内容记录了比较对象的方法、重写实例Equals方法。
139 0
C#(二十五)之C#对象比较
|
iOS开发
OC中的内省方法(Introspection)
OC中的内省方法(Introspection)
155 0