RunLoop个人小结

作者: 百舸争流111 | 来源:发表于2016-08-10 08:12 被阅读64次

1.RunLoop 的概念


程序生命周期

一般来讲,一个线程执行完成任务后就会退出。如果我们需要一个机制,让线程能随时处理事件但并不退出,这时候就需要一个do-while循环,RunLoop(这种模型通常被称作 Event Loop)其内部就是个do-while的无限循环

相关:
事件响应

手势识别

界面更新

定时器

PerformSelecter

关于GCD

关于网络请求

RunLoop 的实际应用举例

AFNetworking

AsyncDisplayKit

2.RunLoop 结构和输入源类型


Runloop的结构和输入源类型

个人认为:每个线程都是RunLoop的载体,同时也决定了程序的生命周期

其次,也是很重要的一点,使用run loop可以使你的线程在有工作的时候工作,没有工作的时候休眠,这可以大大节省系统资源。

3.RunLoop 的内部逻辑

可以看到,实际上 RunLoop 就是这样一个函数,其内部是一个 do-while 循环。当你调用 CFRunLoopRun() 时,线程就会一直停留在这个循环里;直到超时或被手动停止,该函数才会返回。
具体消息的处理,在NSRunLoop中每一个消息就被打包在input source或者是timer source 中了。

NSTimer

NSTimer 其实就是 CFRunLoopTimerRef,他们之间是 toll-free bridged 的。一个 NSTimer 注册到 RunLoop 后,RunLoop 会为其重复的时间点注册好事件。例如 10:00, 10:10, 10:20 这几个时间点。RunLoop为了节省资源,并不会在非常准确的时间点回调这个Timer。Timer 有个属性叫做 Tolerance (宽容度),标示了当时间点到后,容许有多少最大误差。
如果某个时间点被错过了,例如执行了一个很长的任务,则那个时间点的回调也会跳过去,不会延后执行。就比如等公交,如果 10:10 时我忙着玩手机错过了那个点的公交,那我只能等 10:20 这一趟了。
CADisplayLink 是一个和屏幕刷新率一致的定时器(但实际实现原理更复杂,和 NSTimer 并不一样,其内部实际是操作了一个 Source)。如果在两次屏幕刷新之间执行了一个长任务,那其中就会有一帧被跳过去(和 NSTimer 相似),造成界面卡顿的感觉。在快速滑动TableView时,即使一帧的卡顿也会让用户有所察觉。Facebook 开源的 AsyncDisplayLink 就是为了解决界面卡顿的问题,其内部也用到了 RunLoop,这个稍后我会再单独写一页博客来分析。

//定时器的创建

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:4.0
                                                     target:self
                                                   selector:@selector(backgroundThreadFire:) userInfo:nil
                                                    repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timerforMode:NSDefaultRunLoopMode];

PerformSelecter

当调用 NSObject 的 performSelecter:afterDelay: 后,实际上其内部会创建一个 Timer 并添加到当前线程的 RunLoop 中。所以如果当前线程没有 RunLoop,则这个方法会失效。当调用 performSelector:onThread: 时,实际上其会创建一个 Timer 加到对应的线程去,同样的,如果对应线程没有 RunLoop 该方法也会失效。
//创建方式

[self performSelector:(nonnull SEL) withObject:(nullable id)
afterDelay:(NSTimeInterval)]

**线程 **

主线程的run loop默认是启动的,同时也是UIApplicationMain() 函数设置的NSRunLoop 对象,也就是我们一直讨论的RunLoop.
其他线程默认是关闭的 -->需要手动开启
苹果不允许直接创建 RunLoop,它只提供了两个自动获取的函数:CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。
//获取当前线程的RunLoop

NSRunLoop   *runloop = [NSRunLoop currentRunLoop];

手势

当上面的 _UIApplicationHandleEventQueue() 识别了一个手势时,其首先会调用 Cancel 将当前的 touchesBegin/Move/End 系列回调打断。随后系统将对应的 UIGestureRecognizer 标记为待处理。

苹果注册了一个 Observer 监测 BeforeWaiting (Loop即将进入休眠) 事件,这个Observer的回调函数是 _UIGestureRecognizerUpdateObserver(),其内部会获取所有刚被标记为待处理的 GestureRecognizer,并执行GestureRecognizer的回调。

当有 UIGestureRecognizer 的变化(创建/销毁/状态改变)时,这个回调都会进行相应处理。

相关文章

  • NSRunLoop

    【iOS程序启动与运转】- RunLoop个人小结 RunLoop总结:RunLoop的应用场景(三) 走进Run...

  • RunLoop个人小结

    1.RunLoop 的概念 一般来讲,一个线程执行完成任务后就会退出。如果我们需要一个机制,让线程能随时处理事件但...

  • RunLoop个人小结

    一、线程与run loop 1.1 线程任务的类型 再来说说线程。有些线程执行的任务是一条直线,起点到终点;而另一...

  • runLoop小结

    1、runloop和线程有什么关系? runloop:正如其名,loop表示某种循环,和run放在一起就是表示一直...

  • Runloop小结

    作用: 是一个死循环,保持线程活着,有活干活,没活休眠。而不会让一个线程一个任务执行完了,马上释放掉。 Runlo...

  • RunLoop小结

    一、先来几个问题 1.在viewDidLoad中添加3个循环的timer,这3个timer都会访问并且改变一个可变...

  • runloop 小结

    OC的两大核心runtime和runloop runloop简介 runloop本质上是一个do-while循环,...

  • RunLoop入门学习补充资料

    本文是对iOS RunLoop入门小结一文的资料补充 1.RunLoop运行逻辑 以下是伪代码1,摘自https:...

  • 浅谈RunLoop

    由于各种原因,需要对RunLoop进行研究,通过阅读大神的文章对RunLoop也有了一些了解,在这里进行下小结。 ...

  • iOS RunLoop小结

    原文链接:http://yupeng.fun/2019/05/30/runloop/ RunLoop 简介 Run...

网友评论

    本文标题:RunLoop个人小结

    本文链接:https://www.haomeiwen.com/subject/anmlsttx.html