2013年2月14日木曜日

スレッドでビューを更新しているバグを見つける

Method Swizzlingを使い、-[UIView setNeedsDisplay] を置き換えてメインスレッド以外で呼び出されるケースを検出するという話。


(void)toggleViewMainQueueChecking
{
    [UIView swizzleMethod:@selector(setNeedsLayout) 
            withMethod:@selector(_setNeedsLayout_MainQueueCheck)];
    [UIView swizzleMethod:@selector(setNeedsDisplay) 
            withMethod:@selector(_setNeedsDisplay_MainQueueCheck)];
    [UIView swizzleMethod:@selector(setNeedsDisplayInRect:)
            withMethod:@selector(_setNeedsDisplayInRect_MainQueueCheck:)];
}

そしてこんな感じで仕掛けておく
- (void)methodCalledNotFromMainQueue:(NSString *)methodName
{
    NSLog(@"-[%@ %@] being called on background queue. Break on -[UIView methodCalledNotFromMainQueue:] to find out where", NSStringFromClass([self class]), methodName);
}
 
- (void)_setNeedsLayout_MainQueueCheck
{
    if (dispatch_get_current_queue() != dispatch_get_main_queue())
    {
        [self methodCalledNotFromMainQueue:NSStringFromSelector(_cmd)];
    }
 
    // not really an endless loop, this calls the original
    [self _setNeedsLayout_MainQueueCheck]; 
}

シンボルブレークポイントを仕掛けておくと便利。



仕組みは単純だがいいアイディア。


0 件のコメント:

コメントを投稿