【OC底層】AssociatedObject 關聯對象

如何實現給分類「添加成員變量」?

  • 默認狀況下,由於分類底層結構的限制,不能添加成員變量到分類中。但能夠經過關聯對象來間接實現
  • 關聯對象提供瞭如下API

  1> 添加關聯對象atom

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

  2> 得到關聯對象指針

  id objc_getAssociatedObject(id object, const void * key)code

  3> 移除全部的關聯對象對象

  void objc_removeAssociatedObjects(id object) blog

 

key的常見用法

 

objc_AssociationPolicy修飾符

 

 

給分類添加屬性實例

假如已經有一個 XGPerson的類,如今咱們須要擴展這個類,而且添加一個 age 屬性內存

#import "XGPerson.h"

// 分類屬性是不會生成 get\set 方法的,若是不重寫這兩個方法,就沒法正常使用屬性
@interface XGPerson (Test)

@property (nonatomic,assign) int age;

@end
#import "XGPerson+Test.h"
#import <objc/runtime.h>

@implementation XGPerson (Test)


- (void)setAge:(int)age{
    
    // @selector(age) 這個參數只要傳一個地址指針就能夠
    objc_setAssociatedObject(self, @selector(age), @(age), OBJC_ASSOCIATION_ASSIGN);
}

- (int)age{
    
    // 隱式參數
    // _cmd = @selectior(age)
    return [objc_getAssociatedObject(self, _cmd) intValue];
}

調用:ci

        XGPerson* p1 = [[XGPerson alloc]init];
        p1.name = @"p1";
        p1.age = 18;
        
        XGPerson* p2 = [[XGPerson alloc]init];
        p2.name = @"p2";
        p2.age = 20;
        
        NSLog(@"p1Name:%@  p1Age:%i----p2Name:%@  p2Age:%i",p1.name,p1.age,p2.name,p2.age);

輸出:rem

2018-11-29 14:20:38.666084+0800 關聯對象(增長分類屬性)[1923:87124] p1Name:p1  p1Age:18----p2Name:p2  p2Age:20

 

關聯對象的原理

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

  AssociationsManager
  AssociationsHashMap
  ObjectAssociationMap
  ObjcAssociation get

  •  objc4源碼解讀:objc-references.mm

   

  • 關聯對象存儲結構圖

  1. 關聯對象並非存儲在被關聯對象自己內存中
  2. 關聯對象存儲在全局的統一的一個AssociationsManager中
  3. 設置關聯對象爲nil,就至關因而移除關聯對象
相關文章
相關標籤/搜索