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

Objective-C Runtime 核心技術總結:動態方法替換、消息轉發與屬性遍歷

     編輯:關於C語言

Objective-C Runtime 核心技術總結:動態方法替換、消息轉發與屬性遍歷

Objective-C Runtime 賦予了極強的動態能力:運行時獲取/修改類信息、增刪方法屬性、實現 Hook、消息轉發等。本文總結六大核心要點,附實戰代碼示例。

1. 動態替換/新增方法:class_replaceMethod / class_addMethod

實現類似 Windows Hook 的效果:截獲系統方法調用,注入自定義邏輯(如日誌、埋點)。

IMP originIMP;
NSString *MyUppercaseString(id self, SEL _cmd) {
    NSLog(@"begin uppercaseString");
    NSString *str = originIMP(self, _cmd); // 調用原實現
    NSLog(@"end uppercaseString");
    return str;
}

- (void)testReplaceMethod {
    Class cls = [NSString class];
    SEL sel = @selector(uppercaseString);
    originIMP = [NSString instanceMethodForSelector:sel]; // 保存原 IMP
    class_replaceMethod(cls, sel, (IMP)MyUppercaseString, NULL); // 替換
    NSString *s = @"hello world";
    NSLog(@"%@", [s uppercaseString]); // 觸發 Hook
}

輸出:begin → end → HELLO WORLD。
class_addMethod 同理可動態新增方法。

2. 消息轉發:forwardingTargetForSelector

當對象無法響應 Selector 時,將其轉發給其他對象處理,避免崩潰,支援裝飾者模式。

- (id)forwardingTargetForSelector:(SEL)aSelector {
    if (aSelector == @selector(uppercaseString))
        return @"hello world"; // 返回 NSString 實例處理
    return [super forwardingTargetForSelector:aSelector];
}

測試:[[CA new] performSelector:@selector(uppercaseString)] → 輸出 HELLO WORLD。

3. 動態添加方法:resolveInstanceMethod

類方法,在無法響應 Selector 時動態添加實現。優先於 forwardingTargetForSelector 觸發。

+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
    if (aSEL == @selector(t)) {
        class_addMethod([self class], aSEL, (IMP)dynamicMethodIMP, "v@:");
        return YES; // 添加成功,後續不再轉發
    }
    return [super resolveInstanceMethod:aSEL];
}

調用順序:
1. 程序啟動早期觸發 resolveInstanceMethod
2. 實際調用時觸發 forwardingTargetForSelector
3. 若轉發失敗(返回 nil),再次觸發 resolveInstanceMethod
4. 仍無實現則崩潰

4. 遍歷屬性:class_copyPropertyList

unsigned int count;
objc_property_t *props = class_copyPropertyList([UIView class], &count);
for(int i = 0; i < count; i++) {
    const char *name = property_getName(props[i]);
    NSLog(@"%@", [NSString stringWithCString:name encoding:NSUTF8StringEncoding]);
}
free(props); // 必須釋放

可獲取 UIView 所有屬性名(如 layer, tag, backgroundColor 等)。

5. 遍歷方法:class_copyMethodList

unsigned int count;
Method *methods = class_copyMethodList([UIView class], &count);
for(int i = 0; i < count; i++) {
    SEL name = method_getName(methods[i]);
    NSLog(@"%@", NSStringFromSelector(name));
}
free(methods);

相關輔助函數:method_getImplementation、method_getTypeEncoding、method_getNumberOfArguments、method_copyReturnType、method_setImplementation。

6. Runtime 能力總結

  • 增加:方法、實例變量、屬性、協議
  • 獲取:方法/屬性/變量列表及詳情、類信息、變量值
  • 替換:對象類別 (object_setClass)、方法實現 (class_replaceMethod)、通過字符串修改變量

善用 Runtime 可實現熱修復、AOP 切面、自動序列化、字典轉模型等高級功能,是 iOS 進階開發必備技能。

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