Debugging UIKit Usage on BG Threads

Based on this awesome cocoanetics post, and updated to work with JRSwizzle, you might find the UIView+Debug category very handy, specially when debugging die hard bugs.

[cc lang=”objc”]
#import “JRSwizzle.h”

@interface UIView (Debug)

@end

@implementation UIView (Debug)

– (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 (![NSThread isMainThread])
{
[self methodCalledNotFromMainQueue:NSStringFromSelector(_cmd)];
}

// not really an endless loop, this calls the original
[self _setNeedsLayout_MainQueueCheck];
}

– (void)_setNeedsDisplay_MainQueueCheck
{
if (![NSThread isMainThread])
{
[self methodCalledNotFromMainQueue:NSStringFromSelector(_cmd)];
}

// not really an endless loop, this calls the original
[self _setNeedsDisplay_MainQueueCheck];
}

– (void)_setNeedsDisplayInRect_MainQueueCheck:(CGRect)rect
{
if (![NSThread isMainThread])
{
[self methodCalledNotFromMainQueue:NSStringFromSelector(_cmd)];
}

// not really an endless loop, this calls the original
[self _setNeedsDisplayInRect_MainQueueCheck:rect];
}

+ (void)toggleViewMainQueueChecking
{
NSError *error = nil;
[UIView jr_swizzleMethod:@selector(setNeedsLayout)
withMethod:@selector(_setNeedsLayout_MainQueueCheck)
error:&error];

[UIView jr_swizzleMethod:@selector(setNeedsDisplay)
withMethod:@selector(_setNeedsDisplay_MainQueueCheck)
error:&error];

[UIView jr_swizzleMethod:@selector(setNeedsDisplayInRect:)
withMethod:@selector(_setNeedsDisplayInRect_MainQueueCheck:)
error:&error];
}

@end

[/cc]