Runloop [备忘录]

Runloop在多线程程序扮演重要角色。
在IOS开发多线程程序除了GCD,NSOperation,NSThread就是Runloop了。

[1]
Runloop就像是视窗编程的消息循环,他会一直接收消息,并且来判断要不要做某件事情事情或是休息,简单来说就是APP的一个do while(),他永远不会停止,只要你的APP有在启动,这个Runloop就一直在运行,负责处理随时送来的事件,例如:用户点击按钮,或者设置固定时间要做的事件,都可以交给runloop去用。

找到别人的runloop的问题
-》原本用timer在固定时间触发,但是在多线程程序下,由于每个事件都会被排程,如果前面运作的时间变长了,就会影响原本我们要触发的时间。

遇到问题:
手指滑动tableview,原本每秒会运作的timer却不起作用,直到放开手指。

解法:
把timer加入runloop就可以可以。

timer = [NSTimer timerWithTimeInterval:1.0 target:selfselector:@selector(updateTime 🙂 userInfo:nil repeats:YES];

[[NSRunLoop mainRunLoop] addTimer:timerforMode:NSRunLoopCommo

[2]

在runloop你必须知道的输入事件
输入源 1.基于端口的源—系统级事件,例如CFWocketRef
2.Custom Input Sources-开发人员用来手动创建源代码
3.Cocoa Perform Selector Source — performSelector方法

计时器源 1.表示计时器事件

观察者事件 1.入口运行循环
2.何时运行循环将要处理计时器。
3.当运行循环将要处理输入源时。
4,当运行循环即将进入睡眠状态时。
5,当运行循环被唤醒时,但是在它处理了唤醒它的事件之前。
6.退出运行循环。

运行循环模式
1.NSDefaultRunLoopMode
2.NSConnectionReplyMode
3.NSModalPanelRunLoopMode
4.NSEventTrackingRunLoopMode
5.NSRunLoopCommonModes

每个模式都有信号源,观察者和计时器。

[常见问题]
1.加入NSTimer后,当你去滑动UI时,主线程的运行循环会转到UITrackingRunLoopMode,造成Timer不会起作用。

[解法]
1.对NSTimer设定运作于NSRunLoopCommonModes,注册到这个模式后,无论目前runloop切换到那个loop后,事件都可以一直运作。

2.在另一个thrad上去执行和处理Timer事件,然后在主线程上更新UI

- (void)startActivationDelayTimer { 
self.activationDelayTimer = [NSTimer
timerWithTimeInterval:self.activationDelay target:self selector:@selector(activationDelayTimerFired) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:self.activationDelayTimer forMode:NSRunLoopCommonModes];
}

参考源代码[等待跟踪]

数据来自
[1]
https://cg2010studio.com/2017/01/07/ios-nsrunloop%E5%92%8Cnstimer/[2]
https://hit-alibaba.github.io/interview/iOS/ObjC-Basic/Runloop.html[3]
http://blog.csdn.net/hejiasu/article/details/62889781