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といったところか。
