oc 基础 - 关联对象 Association

204 阅读2分钟

1. 分类可否添加成员变量 如何添加

不能直接添加成员变量,但是可以间接实现添加

@interface Person : NSobjc // 分类不会生成这个成员变量 { int_age; } 分类中只会生成方法 这个列表

  • (void)setAge:(int)age;
  • (int)age; // 类中会实现 分类不会实现,
  • (void)setAge:(int)age { }
  • (int)age { }

// @property (assing, noatomic) int age; 干了上面三件事

分类中只会生成方法 列表

@end

// 第一种做法 使用字典 储存 @implementation Person

NSMutableDictionary *weight_;

+(void)load { age_ = [[NSMutableDictionary alloc] init] }

  • (void)setAge:(int)age { Nsstring *key = S(@"%p",self); age[key] = age; }

  • (int)age { Nsstring *key = S(@"%p",self); age[key]; }

@end

第二种 关联对象 方式

#import objc/runtime.h

关联对象提供了三个api

  1. 添加关联对象 void objc_setAssociatedObject(id object, const void *key, id value, object_AssociationPolicy policy)

  2. 获得关联对象

id objc_getAssociatedObject(id object, const void *key)

3.移除所有的关联对象

void objc_removeAssciatedObjectes(id object)

@implementation Person

key 的写法

const void *namekey = &namekey

  • (void)setAge:(int)age { iobjc_setAssociatedObject(self, namekey, age, OBJC_ASSCIA_COPY_NOATOMIC)

}

  • (int)age { objc_getAssociatedObject(self, namekey) }

@end

第三种

@implementation Person

key 的写法

static 本文件内使用 增加 char 只占用一个字节 不需要赋值 只用地址值 static const char NameKey;

  • (void)setAge:(int)age { iobjc_setAssociatedObject(self, namekey, age, OBJC_ASSCIA_COPY_NOATOMIC)

}

  • (int)age { objc_getAssociatedObject(self, namekey) }

@end

第四种

@implementation Person

key 的写法 直接使用@"age"

  • (void)setAge:(int)age { iobjc_setAssociatedObject(self, @(age), age, OBJC_ASSCIA_COPY_NOATOMIC)

}

  • (int)age { objc_getAssociatedObject(self, @(age)) }

@end

第五种

@implementation Person

key 的写法

使用@selector(age);

@selector(age) 是一个指向结构体的指针 void *

  • (void)setAge:(int)age { iobjc_setAssociatedObject(self,@selector(age), age, OBJC_ASSCIA_COPY_NOATOMIC)

}

  • (int)age { 隐式参数 相当于
  • (int)age:(id)self _cmd(SEL)_cmd @selector(age) = _cmd; objc_getAssociatedObject(self, @selector(age)) _cmd 代表当前方法的选择器 @selector(age) 所以可以用_cmd 替换 objc_getAssociatedObject(self, _cmd) }

@end

关联对象的实现原理

有4个对象实现

  1. AssociationsManager
  2. AssociationsHashMap
  3. AssociationMap
  4. ObjcAssociation

HashMap 约等于字典

runtime 源码

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

id object == disguised_prt_t == Class

const void *key = void * = @Selector(age) = _cmd

AssociationsManager { AssociationsHashMap { disguised_prt_t : AssociationMap { void * : ObjcAssociation { policy : value policy : value policy : value } void * : ObjcAssociation { policy : value policy : value policy : value } }

      Class : AssociationMap {
          void * : ObjcAssociation {
               policy : value
          }
      }
      
      Person : AssociationMap {
          void * : ObjcAssociation {
               policy : value
          }
      }
  }

}

关联对象不会存储在类中,它存贮在runtime 维护的一个全局地址中 通过一个manager 管理一个二维字典 把每个类的关联对象对应的存储到字典中 policy 没有week 属性