RunLoop就是跑圈, 保证程序一直在执行. App运行起来之后, 即使你什么都不做, 放在那儿它也不会退出, 而是一直在"跑圈", 这就是RunLoop干的事. 主线程会自动创建一个RunLoop来保证程序一直运行. 但子线程默认不创建NSRunLoop, 所以子线程的任务一旦返回, 线程就over了.
RunLoop在某一时刻只能在一种模式下运行, 更换模式时需要暂停当前的Loop, 然后重启新的Loop. RunLoop主要有下面几个模式:
NSDefalutRunLoopMode : 默认Mode, 通常主线程在这个模式下运行
UITrackingRunLoopMode : 滑动ScrollView是会切换到这个模式
NSRunLoopCommonModes: 包括上面两个模式
这边需要特别注意的是, 在滑动ScrollView的情况下, 系统会自动把RunLoop模式切换成UITrackingRunLoopMode来保证ScrollView的流畅性.
[NSTimerscheduledTimerWithTimeInterval:1.f target:selfselector:@selector(timerAction:) userInfo:nilreports:YES];
当你在滑动ScrollView的时候上面的timer会失效, 原因是Timer是默认加在NSDefalutRunLoopMode上的, 而滑动ScrollView后系统把RunLoop切换为UITrackingRunLoopMode, 所以timer就不会执行了. 解决方法是把该Timer加到NSRunLoopCommonModes下, 这样即使滑动ScrollView也不会影响timer了.
[[NSRunLoop currentRunLoop]addTimer:timerforMode:NSRunLoopCommonModes];
另外还有一个trick是当tableview的cell从网络异步加载图片, 加载完成后在主线程刷新显示图片, 这时滑动tableview会造成卡顿. 通常的思路是tableview滑动的时候延迟加载图片, 等停止滑动时再显示图片. 这里可以通过RunLoop来实现.
[self.cellImageView performSelector:@sector(setImage:) withObject:downloadedImage afterDelay:0inModes:@[NSDefaultRunLoopMode]];
当NSRunLoop为NSDefaultRunLoopMode的时候tableview肯定停止滑动了, why? 因为如果还在滑动中, RunLoop的mode应该是UITrackingRunLoopMode.
[[NSThreadcurrentThread] setName:@"AFNetworking"];NSRunLoop*runLoop = [NSRunLoopcurrentRunLoop]; [runLoop addPort:[NSMachPortport] forMode:NSDefaultRunLoopMode]; [runLoop run];
AFNetworking创建了一个新的子线程(在子线程中调用NSRunLoop *runloop = [NSRunLoop currentRunLoop]; 获取RunLoop对象的时候, 就会创建RunLoop), 然后把它加到RunLoop里面来保证它一直运行.
使用CFRunLoop来启动/停止
[self.connection scheduleInRunLoop:[NSRunLoopcurrentRunLoop] forMode:NSRunLoopCommonModes];
CFRunLoopRun();
// CFRunLoopStop()停止
参考: https://www.jianshu.com/p/ebb3e42049fd