theosマクロ(順次追加)

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

%subclass


Makefile

export GO_EASY_ON_ME=1

これが無い場合CFLAGSに-Werrorが設定され、警告をエラー扱いとする。(コンパイルされない)