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]; }
シンボルブレークポイントを仕掛けておくと便利。
仕組みは単純だがいいアイディア。