RunLoop使用示例

1.将定时器添加到NSRunLoopCommonModes中,避免在UITrackingRunLoopMode无法执行

滑动ScrollView后系统把RunLoop切换为UITrackingRunLoopMode,因此加载默认模式中的定时器并不会执行,只有滚动停止回到默认模式才会继续执行。我们可以把定时器设为 NSRunLoopCommonModes的模式,并添加到 run loop 中;
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

2. 在NSDefaultRunLoopMode中加载图片,避免加载图片导致tableView滑动卡顿

当tableview的cell从网络异步加载图片, 加载完成后在主线程刷新显示图片, 这时滑动tableview会造成卡顿. 通常的思路是tableview滑动的时候延迟加载图片, 等停止滑动时再显示图片. 这里我们可以通过RunLoop来实现.
[self.cellImageView performSelector:@sector(setImage:) withObject:downloadedImage afterDelay:0 inModes:@[NSDefaultRunLoopMode]];

3. AFNetworking类似 创建一个常驻的服务线程

+ (void)_networkThreadMain:(id)object {
    @autoreleasepool {
        [[NSThread currentThread] setName:@"我自己的线程"];
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];
    }
    
}




+ (NSThread *)networkThread {
    static NSThread *thread = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        thread = [[NSThread alloc] initWithTarget:self selector:@selector(_networkThreadMain:) object:nil];
        if ([thread respondsToSelector:@selector(setQualityOfService:)]) {
            thread.qualityOfService = NSQualityOfServiceBackground;
        }
        [thread start];
    });
    return thread;
}

在其他地方 通过

        [self performSelector:@selector(testApp) onThread:[RunLoopManager networkThread] withObject:nil waitUntilDone:NO];

4. 让Crash的App回光返照

接到crash的Signal后 手动重启RunLoop

CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    NSArray *allModes = CFBridgingRelease(CFRunLoopCopyAllModes(runLoop));
    while (1) {
        for (NSString *mode in allModes) {
            CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
        }
    }