theos frameworkにおけるマクロの備忘録。順次追加予定。
Tweak.xm
%hook~%end
下記の形式でClassName内におけるメソッドを改変する。%hook ClassName method %end
%orig; %orig(id);
%hook~%end内の改変メソッド内で有効。該当メソッドのオリジナルの動作に展開される。
引数を記述した場合、メソッドへの引数として常にその値が使用される。
メソッドの返り値がvoidでない限り、本来そのメソッドが返す返り値を返り値とする。
例えば下記のようにすると返り値の調査が行える。
(クラッシュする場合%@を変更しよう、書式が違う可能性もある)
- (id)sampleMethod { id temp = %orig; NSLog(@"%@", temp); NSLog(@"return class is %@", NSStringFromClass([temp class])); // by @tom_go return temp; }
%log;
NSLogで引数や型情報など、調査する際に書く内容の簡略化。%hook UIApplication - (BOOL)canOpenURL:(NSURL *)url { %log; } %end
と書くと以下のように展開される。
NSLog(@"-[ <UIApplication: %p> canOpenURL:%@]", self, url);
%ctor
static __attribute__((constructor)) void _logosLocalCtor_の簡略化。%c(ClassName)
ClassNameクラス型の取得。objc_getClass("ClassName")の簡略化。2011/07/19 update
%c(SampleClass)は$SampleClassへと置換され、
static Class $SampleClass; の宣言に加え、
static __attribute__((constructor)) void関数にて
Class $$SampleClass = objc_getClass("SampleClass");
が行われる。
つまり一度この形式で記述した箇所があれば、$SampleClassでアクセスできる。
が、メンテナンス性と可読性から常に%cを使うか、
%classを使用し全て$SampleClassで書くのが良いだろう。
%group~%end
下記の形式で%hook~%endをグループ化する。グループ化した場合は%init(GroupName);を実行する事でグループ内のhookが有効となる。
OSバージョン毎に有効無効を切り分ける際に有用。
%group使用時にグループ化されていない%hookを有効とするには%init;を実行すればよい。
%group GroupName %hook ClassName method %end %end
%hook ClassName method %group GroupName method %end %end
%new
%hook~%end内は通常既存メソッドの改変を行うが、カテゴリのようにメソッドの追加も行える。下記のようにメソッドの直前に記述する。
括弧の中身でメソッドの実装であるIMP、つまりC関数の引数の型を記述する。この時の記号はメソッドエンコーディングに準ずる。
v=void
@=object
i=int(NSInteger、NSUInteger含む)
c=char(BOOL含む)
%new(v@:) - (void)sampleMethod{ }
%class
%class SampleClassと記述した場合、static Class $SampleClass; の宣言に加え、
static __attribute__((constructor)) void関数にて
Class $$SampleClass = objc_getClass("SampleClass");
が行われる。
同様の処理が%c(ClassName)でも行われるが、
グローバル変数を定義する行の近くで記述し、
明示的に行いたい場合に使用できるだろう。
独自クラス版の@classといったところか。