1.讲讲RunLoop,项目中有用到吗?
RunLoop 翻译过来是运行循环,指的是在程序运行过程中循环做一些事情.
基本作用:
- 保持程序的持续运行
- 处理App中的各种事件
- 节省CPU资源,提高程序性能(该做事时做事,该休息时休息)
应用范畴有:
- 定时器(NSTimer),PerformSelector
- GCD Async Main Queue
- 时间响应,手势识别,界面刷新
- 网络请求
- AutoreleasePool
2.RunLoop内部的实现逻辑
- 01.通知Observers: 进入Loop
- 02.通知Observers: 即将处理Timers
- 03.通知Observers: 即将处理Sources
- 04.处理Blocks
- 05.处理Source0(可能再次处理Blocks)
- 06.如果存在Source1,就直接跳第8步
- 07.通知Observers: 开始休眠(等待消息唤醒)
- 08.通知Observers:结束休眠(被某个消息唤醒)
- 处理Timer
- 处理GCD Async To Main Queue
- 处理Sourcel
- 09.处理blocks
- 10.根据前面的执行结果,决定如何操作
- a> 回到第02步
- b> 退出Loop
- 11.通知Observers: 退出Loop
3.RunLoop和线程的关系
- 每一条线程都有唯一的一个与之对应的RunLoop对象
- RunLoop保存在全局的Dictionary里,线程作为key,RunLoop作为value
- 线程刚刚创建的时候是没有RunLoop的,在第一次获取的时候创建
- RunLoop会在线程结束的时候销毁
- 主线程的RunLoop已经自动获取,子线程默认没有开启RunLoop
4.timer和RunLoop的关系
5.RunLoop是怎么响应用户操作的,具体流程是什么?
先由Sourcel1进行补抓,然后交于Source0进行处理
6.说说RunLoop的几种状态
kCFRunLoopEntry = (1UL << 0), // 进入Loop
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理NSTimer
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理Sources
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将被唤醒
kCFRunLoopAfterWaiting = (1UL << 6), // 即将休眠
kCFRunLoopExit = (1UL << 7), // 退出
kCFRunLoopAllActivities = 0x0FFFFFFFU
7.RunLoop的mode作用是什么?
一个RunLoop包含若干的Mode,每个Mode又包含若干个Source0/Source1/Observer
常见的mode有两种
kCFRunLoopDefaultMode App的默认mode,通常主线程是在这个Mode下运行
UITrackingRunLoopMode: 界面追踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时候不受其他的Mode影响
注意
NSDefaultRunLoopMode 和 UITrackingRunLoopMode 是真正存在的模式
NSRunLoopCommonModes并不是一个真的模式,它只是一个标记
timer能在_commonModes数组中存放的模式下工作
8.RunLoop在实际开发中的作用
控制线程生命周期
- (void)viewDidLoad {
[super viewDidLoad];
MJThread *thread = [[MJThread alloc] initWithTarget:self selector:@selector(run) object:nil];
thread.name = @"MJThread";
[thread start];
self.mj_thread = thread;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// waitUntilDone: YES:等当test方法执行完后在执行下面的代码 NO:不需要等test方法,直接执行下面的代码
[self performSelector:@selector(test) onThread:self.mj_thread withObject:nil waitUntilDone:NO];
NSLog(@"哈哈哈");
}
- (void)test
{
NSLog(@"%s--%@",__func__,[NSThread currentThread]);
}
- (void)run
{
// 如果RunLoop中没有Source0 Source1 timer Observers 的话,会立刻退出
[[NSRunLoop currentRunLoop] addPort:[[NSPort alloc]init] forMode:NSDefaultRunLoopMode];
// 利用[NSRunLoop currentRunLoop],保住线程不被释放
[[NSRunLoop currentRunLoop] run];
NSLog(@"--end--");
}
解决NSTimer在滑动时停止工作的问题
监控应用卡顿
性能优化