首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Objective-C 對象模型與 Runtime 機制深度解析:isa、類/元類、消息轉發、方法緩存、關聯對象

     編輯:關於C語言

Objective-C 對象模型與 Runtime 機制深度解析:isa、類/元類、消息轉發、方法緩存、關聯對象

Objective-C 的動態特性源於其獨特的對象模型與 Runtime 系統。本文從結構體定義出發,層層剖析實例對象、類對象、元類對象的 isa 指針鏈、消息發送流程、動態方法解析、完整消息轉發、方法緩存優化、關聯對象實現,並給出調試技巧與實戰應用模式。

一、核心結構體定義

// objc.h 簡化版
typedef struct objc_object *id;
typedef struct objc_class *Class;

struct objc_object {
    Class isa; // 實例對象指向其類對象
};

struct objc_class {
    Class isa;              // 類對象指向其元類對象
    Class superclass;       // 父類指針
    const char *name;       // 類名
    // ... 以下為舊版 ABI 字段,現代 Runtime 通過 bits 存儲
    struct objc_ivar_list *ivars;        // 實例變量列表
    struct objc_method_list **methodLists; // 方法列表
    struct objc_cache *cache;            // 方法緩存
    struct objc_protocol_list *protocols; // 協議列表
};

二、對象模型三層關係圖

實例對象 (instance)
    isa ──→ 類對象 (Class Object)  [存儲實例方法、實例變量佈局]
                isa ──→ 元類對象 (Meta Class) [存儲類方法]
                        isa ──→ 基類元類 (NSObject Meta) → isa 指向自身 (閉環)
                superclass ──→ 父類對象
                        superclass ──→ ... → NSObject 類對象 → superclass = nil
  • 實例對象:id 類型,內存佈局首字段為 isa,隨後是實例變量。
  • 類對象:單例,存儲實例方法(-)、實例變量描述、屬性、協議、緩存。
  • 元類對象:單例,存儲類方法(+),isa 指向基類元類,構成閉環。

三、消息發送流程

// 編譯器將 [receiver message] 轉為:
id objc_msgSend(id self, SEL op, ...);

// objc_msgSend 核心邏輯(偽代碼)
id objc_msgSend(id self, SEL op, ...) {
    Class cls = self->isa;
    // 1. 快速路徑:緩存查找
    IMP imp = cache_get(cls->cache, op);
    if (imp) return imp(self, op, ...);

    // 2. 慢速路徑:方法列表遍歷
    imp = class_getMethodImplementation(cls, op);
    if (imp) {
        cache_add(cls->cache, op, imp); // 填充緩存
        return imp(self, op, ...);
    }

    // 3. 向上查找父類鏈
    for (Class super = cls->superclass; super; super = super->superclass) {
        imp = class_getMethodImplementation(super, op);
        if (imp) {
            cache_add(cls->cache, op, imp);
            return imp(self, op, ...);
        }
    }

    // 4. 消息轉發入口
    return objc_msgSend_forward(self, op, ...);
}

四、消息轉發機制(三級兜底)

  1. 動態方法解析:+ (BOOL)resolveInstanceMethod:(SEL)sel / resolveClassMethod:
    可在運行時動態添加方法實現(如 class_addMethod),返回 YES 重新進入發送流程。
  2. 快速轉發:- (id)forwardingTargetForSelector:(SEL)sel
    返回一個替代目標對象,消息將直接轉發給該對象,不創建 NSInvocation,性能最佳。
  3. 完整轉發:- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel + - (void)forwardInvocation:(NSInvocation *)inv
    構建完整調用上下文(參數、返回值、目標),支持參數修改、多目標分發、異步轉發。
// 示例:動態添加屬性存取器
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    const char *name = sel_getName(sel);
    if (strncmp(name, "set", 3) == 0 || strncmp(name, "get", 3) == 0) {
        class_addMethod(self, sel, (IMP)dynamicAccessor, "v@:@");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

五、方法緩存優化

  • 緩存結構:哈希表(bucket_t 數組),鍵為 SEL,值為 IMP。
  • 查找:mask = allocated - 1; index = (sel >> 2) & mask; 開放寻址法解決衝突。
  • 擴容:負載因子超 3/4 時翻倍重哈希。
  • 特點:只緩存實例方法,類方法走元類緩存。objc_msgSend 先查緩存,命中率極高(>95%)。

六、關聯對象:為現有類動態添加「實例變量」

// API
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);

// 策略枚舉
typedef enum {
    OBJC_ASSOCIATION_ASSIGN = 0,           // 弱引用
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 強引用,非原子
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   // 複製,非原子
    OBJC_ASSOCIATION_RETAIN = 01401,       // 強引用,原子
    OBJC_ASSOCIATION_COPY = 01403          // 複製,原子
} objc_AssociationPolicy;

// 實現原理:全局哈希表 (AssociationsHashMap),鍵 = 對象地址 + key,值 = ObjcAssociation(value, policy)
// 對象 dealloc 時,Runtime 遍歷關聯表釋放/複製對應 value。

應用場景:Category 中添加存儲屬性、KVO 輔助、運行時擴展系統類行為。

七、實戰調試技巧

需求命令/代碼
打印對象 isa 類名po (id)[obj class] / po object_getClass(obj)
列出類所有方法po [MyClass methodList] (需分類) / class_copyMethodList
動態添加方法class_addMethod(cls, @selector(newMethod), (IMP)func, "v@:")
交換方法method_exchangeImplementations(m1, m2) (Method Swizzling)
查看消息轉發調用棧在 forwardInvocation: 設置斷點,bt

八、總結

Objective-C Runtime 以 isa 指針鏈構建對象模型、雙層查找(緩存+列表)加速消息發送、三級轉發機制保證動態性、關聯對象突破編譯時佈局限制。深入理解這些機制,是掌握 KVO/KVC、Method Swizzling、動態代理、熱修復、組件化解耦等高級技術的前提。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved