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.

#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

Leave a Reply