ObjecTips

Swift & Objective-C で iOS とか macOS とか

メソッド置換

Runtime APImethod_exchangeImplementations というメソッド置換を行う関数がある。
メソッド交換、メソッド置き換え、メソッド入れ替えなどとも呼ばれる。

実装は簡単
objc/runtime.h をimportして

    Class cls;
    Method m1 = class_getInstanceMethod(cls, @selector(methodA));
    Method m2 = class_getInstanceMethod(cls, @selector(methodB));
    method_exchangeImplementations(m1, m2);

runtime.h の記述によると以下が atomically なバージョンの実装とのこと。

    IMP imp1 = method_getImplementation(m1);
    IMP imp2 = method_getImplementation(m2);
    method_setImplementation(m1, imp2);
    method_setImplementation(m2, imp1);

ビルドできる実装例は以下

例えば上の例では methodA を呼び出すと methodB called とログが出力される。

下の例では methodB 内で methodB を呼び出す事で、methodB 内からメソッド置換された methodB つまり methodA を呼び出している。
ログには methodB called methodA called の順で出力される。

この置換とメソッドの呼び出しの仕組みを使えば、SystemFramework の既存クラスをフックしてメソッドが実行される前に自前の処理を挟むような事もできるので、中で何が行われているのかを調べるのにも便利。