Objective-C 作為動態語言,其對象模型是理解運行時機制、KVO、Method Swizzling 等高級特性的基石。本文從 isa 指針、類結構、元類繼承、成員變量佈局、動態性三大維度深度剖析,並結合系統 API 實戰與開源項目案例,助你構建完整認知體系。
每個 OC 對象首字段均為 isa 指針,指向其類對象。類對象同樣擁有 isa,指向元類。元類保存類方法,其 isa 最终指向根元類形成閉環。這一定義了「一切皆對象」的純粹性。
// NSObject 定義簡化
struct NSObject {
Class isa;
};
// Class 定義簡化
struct objc_class {
Class isa; // 指向元類
Class super_class; // 父類
// ... methodLists, cache, ivars 等
};
圖解關係:
對象內存佈局等同於 C 結構體:首字段 isa,其後按聲明順序排列父類至子類所有 ivars。驗證代碼:
@interface Father : NSObject { int _father; } @end
@interface Child : Father { int _child; } @end
// lldb 輸出:
// (Child) $0 = { (Father) Father = { (NSObject) NSObject = { (Class) isa = Child } (int) _father = 0 } (int) _child = 0 }
方法定義存儲於類的可變區域 methodLists,Category 通過修改指針鏈實現動態添加方法。這也是為什麼 Category 不能添加 ivars(結構體大小固定)的原因。關聯對象(objc_setAssociatedObject)通過外部哈希表實現偽 ivars。
系統 KVO 實現利用 isa-swizzling:觀察對象時,將其 isa 指向動態生成的中間類,中間類重寫 setter 觸發通知。警示:永不可依賴 isa 判斷類型,應用 [obj class]。
| API | 行為差異 | 適用場景 |
|---|---|---|
class_replaceMethod | 無原方法時自動 class_addMethod,需 types 參數 | 目標方法可能不存在(如動態添加) |
method_exchangeImplementations | 雙向交換實現,內部調用兩次 method_setImplementation | 需完整保留原實現並雙向替換(經典 Swizzling) |
method_setImplementation | 單向設置新實現,最簡單直接 | 純替換不需保留原實現 |
源碼參考:

// 替換類實現
@implementation ImagePickerReplaceMethodsHolder
- (BOOL)shouldAutorotate { return NO; }
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; }
@end
// 運行時交換
Method orig1 = class_getInstanceMethod([UIImagePickerController class], @selector(shouldAutorotate));
Method new1 = class_getInstanceMethod([ImagePickerReplaceMethodsHolder class], @selector(shouldAutorotate));
method_exchangeImplementations(orig1, new1);
AFHTTPRequestOperation.m 使用 class_replaceMethod 動態替換響應序列化邏輯。NIRuntimeClassModifications.h 統一運行時修改入口。class_replaceMethod。結論:合理使用 Method Swizzling 不會導致 App Store 拒審,關鍵在於不濫用、不破壞系統完整性、保持調用鏈完整。