通过内部维护的事件循环来对事件或者消息进行管理的一个对象
不要说运行循环,说是用户态到内核态,内核态到用户态的转
1)'kCFRunLoopDefaultMode':App的默认Mode,通常主线程是在这个Mode下运行
2)'UITrackingRunLoopMode':界面跟踪 Mode,用于 ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode 影响
3)'UIInitializationRunLoopMode': 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
4)'GSEventReceiveRunLoopMode': 接受系统事件的内部 Mode,通常用不到
5)'kCFRunLoopCommonModes': 这是一个占位用的Mode,不是一种真正的Mode
/*
CommonMode并不是一种实际的模式,和defaultmode完全不是一回事。简单的理解就是,如果设置了CommonMode模式,那么runloop在切换mode的同时,也把timer的事件也带走了,所以无论切到哪种mode下,timer的事件都是可以处理的。
*/
Q:滑动tableView的时候,timer事件的轮播器不走了。
分析: 到底是什么原因。
解决办法:大家都知道,timer的mode从defaultmode,换到CommonMode就可以了。
问题:为什么为什么就可以了。
回答tableView滚动timer不走问题:
1.默认滚动事件和timer事件都是在kCFRunloopDefaultMode下的
2.此时tableView一滚动,mode切换到UITrackingRunloopMode中,上面说,runloop同一时间只能处理一种mode的事件,那么在DefaultMode的timer就无法响应了。
3.CommonMode又是一个同步多种mode的技术方案,此模式下,当runloop到UITrackingRunloopMode的时候,他把timer的事件也转移到UITrackingRunloopMode下,那么timer就能走了。
常驻线程
(NSThread *)networkRequestThread {
static NSThread *_networkRequestThread = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
[_networkRequestThread start];
});
return _networkRequestThread;
}(void)networkRequestThreadEntryPoint:(id)__unused object {
@autoreleasepool {
[[NSThread currentThread] setName:@"AFNetworking"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
移除常驻线程方法
/// 停止常驻线程
{
self.stopLoopRunning = YES;
// 移除 port
// 如果是用 timer 的方式的常驻线程, 可以 invalid 对应的 timer
[self.threadRunLoop removePort:self.threadPort forMode:NSRunLoopCommonModes];
// 停止 RunLoop
if (nil != self.threadRunLoop) {
CFRunLoopStop([self.threadRunLoop getCFRunLoop]);
}
}
http://www.veryitman.com/2018/07/01/RunLoop-移除常驻线程/
https://blog.csdn.net/u014795020/article/details/72084735
https://blog.csdn.net/xiaoxiaobukuang/article/details/80021616