By | 2013年3月10日

UIView Background Queue Debugging をみてこれいいなと思ってたんですけど、 swizzle を使ってたり別途クラスを定義したりとしてたのでもっと手軽にできたりしないのかなーと思ってたところで「BlockInjectionで元のソースコードを汚さないで振る舞い追加」を見てこれだ!!
となったわけでさっそく試してみました。

インストールも Cocoapods を使えば簡単にいけますね。

[BILib injectToSelector:@selector(setNeedsLayout) forClass:[UIView class] preprocess:^(UIView *view) {
    if (dispatch_get_current_queue() != dispatch_get_main_queue())
        NSLog(@"[%@ setNeedsLayout] being called on background queue.", NSStringFromClass([view class]));
}];
[BILib injectToSelector:@selector(setNeedsDisplay) forClass:[UIView class] preprocess:^(UIView *view) {
    if (dispatch_get_current_queue() != dispatch_get_main_queue())
        NSLog(@"[%@ setNeedsDisplay] being called on background queue.", NSStringFromClass([view class]));
}];
[BILib injectToSelector:@selector(setNeedsDisplayInRect:) forClass:[UIView class] preprocess:^(UIView *view, CGRect frame) {
    if (dispatch_get_current_queue() != dispatch_get_main_queue())
        NSLog(@"[%@ setNeedsDisplayInRect:%@] being called on background queue.", NSStringFromClass([view class]), NSStringFromCGRect(frame));
}];

これを application:didFinishLaunchingWithOptions:launchOptions で定義して使っています。
ついでにブレークポイントをしかけてクラッシュ前に捕まえられて状況を把握できるのでデバッグも効率的にできるわけですね。
地味に再現がめんどくさかったりするのでこういうのは助かりますね。

あと dispatch_get_current_queue は iOS6 から duplicated になっています。
Queue 名をつけて dispatch_get_specific で取得するようにしないといけなくなったのが少しめんどくさいですね

デバッグ時にも役立つし効果測定のコードも Controller から分離できそうなんでしばらく使ってみようかなと思います。