4. OC語法-關聯對象

一、思考:如何實現給分類“添加成員變量”?

  • 默認情況下,因爲分類底層結構的限制,不能添加成員變量到分類中。但可以通過關聯對象來間接實現

  • 關聯對象提供了以下API

// 添加關聯對象
/*
id object: 要關聯的對象
const void * key: 關聯屬性的key
id value: 要關聯的屬性值
objc_AssociationPolicy 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)

二、key的常見用法

  • 方式一: 使用指針變量作爲key
// 爲啥使用static, 不要用全局的指針變量, 外界可以修改, 導致數據出錯
static void *MyKey = &MyKey;
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
objc_getAssociatedObject(obj, MyKey)
  • 方式二: 使用常量的地址作爲key
// 爲啥用char, 因爲char類型的常量只有1個字節
static const char MyKey;
objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
objc_getAssociatedObject(obj, &MyKey)
  • 方式三: 使用屬性名作爲key
objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_COPY_NONATOMIC); 
objc_getAssociatedObject(obj, @"property");
  • 方式四(推薦):使用get方法的@selecor作爲key
objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
// _cmd == @selector(getter)
// objc_getAssociatedObject(obj, @selector(getter))
objc_getAssociatedObject(self, _cmd);

三、objc_AssociationPolicy

在這裏插入圖片描述

四、關聯對象的原理

  • 實現關聯對象技術的核心對象有

    • AssociationsManager
    • AssociationsHashMap
    • ObjectAssociationMap
    • ObjcAssociation
  • objc4源碼解讀:objc-references.mm
    在這裏插入圖片描述

五、關聯對象的原理

void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)
  • 關聯對象並不是存儲在被關聯對象本身內存中
  • 關聯對象存儲在全局的統一的一個AssociationsManager中
  • 設置關聯對象爲nil,就相當於是移除關聯對象

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章