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

Objective-C 運行時動態獲取私有實例變量

     編輯:關於C語言

場景:單元測試/調試/熱修復需訪問私有 ivar

Objective-C 編譯期強制封裝(@private),但運行時提供 C API 繞過檢查。

核心 API:object_getInstanceVariable

#import <objc/runtime.h>

// 類定義
@interface Mobj : NSObject {
@private
    NSString* mt_;
}
@end

@implementation Mobj
- (instancetype)init {
    self = [super init];
    if (self) mt_ = [[NSString alloc] initWithString:@"Ha Ha Ha"];
    return self;
}
- (void)dealloc { [mt_ release]; [super dealloc]; }
@end

// 獲取私有變量
Mobj* obj = [[Mobj alloc] init];
NSString* str = nil;
object_getInstanceVariable(obj, "mt_", (void**)&str); // 關鍵調用
NSLog(@"%@", str); // 輸出: Ha Ha Ha
[obj release];

參數詳解

  • id obj:目標對象實例。
  • const char* name:ivar 名稱(C 字符串,需與聲明一致,含下劃線)。
  • void** outValue:輸出參數,接收 ivar 存儲的指針值(對象類型),或基本類型值(需強轉)。

配套 API 族

現代替代:KVC (Key-Value Coding)

NSString* str = [obj valueForKey:@"mt_"]; // 自動搜尋 _mt_, mt_, getMt_ 等
// 需確保類未重寫 -valueForUndefinedKey: 拋出異常

KVC 更安全、可讀,但私有 ivar 仍可能被 accessInstanceVariablesDirectly 返回 NO 而阻擋。

⚠️ 警示與最佳實踐

  1. 僅限調試/測試/熱修復:生產代碼嚴禁依賴私有 ivar,版本升級極易崩潰。
  2. ARC 環境下注意所有權:獲取對象指針後需手動 __strong 管理,否則可能過早釋放或洩漏。
  3. 類擴展優於運行時 Hack:同一模塊內用 @interface Mobj () @property (nonatomic, strong) NSString* mt_; @end 暴露給友元類。
  4. Swift 不適用:Swift 無運行時 ivar 直接訪問機制(除非 @objc 繼承 NSObject 且用 KVC)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
函數用途
class_getInstanceVariable從 Class 獲取 Ivar 結構體,再用 ivar_getOffset 計算偏移
object_getIvar / object_setIvar直接按 Ivar* 讀寫,性能更高
ivar_getName / ivar_getTypeEncoding獲取名稱/@encode 類型字符串