Runloop

Runloop 概念和本质

RunLoop是一个对象,用于管理需要处理的事件和消息。

一个runloop就是一个事件处理循环,用来不停的调度工作以及处理输入事件。目的是让线程在有工作的时候忙于工作,没工作的时候处于休眠状态。

runloop实现原理(或者本质)

runloop是一个do while死循环。循环中一直进行的逻辑是:“接受消息->等待->处理”,直到循环结束(比如quit消息)

ios中的runloop对象有那些

Foundation框架的NSRunLoop,提供了面向对象的 API,但是这些 API 不是线程安全的。

Core Foundation框架的CFRunloopRef,它提供了纯 C 函数的 API,所有这些 API 都是线程安全的。

RunLoop和线程的关系

  • 1.runloop和线程是一一对应的。

    每条线程都有唯一一个和他对应的RunLoop对象,二者是利用字典来存储,key是线程,Value是该线程对应的Runloop

  • 2.ios不允许直接创建RunLoop,只允许获取runloop对象。而且RunLoop是在第一次获取时创建,在线程结束时销毁

3.主线程的Runloop系统已自动创建,并开启

4.子线程默认没有开启RunLoop,需主动获取,子线程常驻的时候需要开启runloop

[NSRunLoop currentRunLoop]; 获得当前线程的 RunLoop对象 [NSRunLoop mainRunLoop]; 获得主线程的RunLoop对象

获取线程runloop对象的底层实现原理:

首先在保存线程和runloop的字典中以线程为key查找所需runloop,如果有则直接返回。如果无则创建一个runloop,并保存到字典中,然后返回这个runloop。说明了runloop和线程是一一对应关系,也说明是懒加载的创建模式,即需要时才创建。

Runloop对象的组成:

image Runloop对象中包含多个model。每一个model包含若干个source, observer,timer

Source是事件源,比如触摸事件,输入事件

Observer是观察者,监听RunLoop的状态

Timers:计时器

runloop处理的事件源有哪些?

source事件(包括Source0事件,Source1事件)

Observer事件(指runloop中状态变化时进行通知)

Timer事件

其他(Block事件,Main_Dispatch_Queue事件)

Mode是RunLoop的运行模式,有五类:

mode 分类 default. tracking, init, eventReceive, common

NSDefaultRunLoopMode:app默认mode。通常⽤用于主线程。

UITrackingRunLoopMode:界⾯面跟踪model,⽤用于scrollview追踪触摸互动。

kCFRunLoopCommonModes = NSDefaultRunLoopMode + UITrackingRunLoopMode

UIInitializationRunLoopMode:在app刚启动的进⼊入的第⼀个model,启动后就不再使⽤

GSEventReceiveRunLoopMode:接收系统事件内部mode,通常⽤用不不到

RunLoopmode的注意事项

1.RunLoop启动时只能选择其中一个Mode作为currentMode

2.如果需要切换Mode,只能退出当前Loop,再重新选择一个Mode进入。,目的是分开各个mode,免其相互影响

3.如果Mode里没有sources0/sources1/Timer/observer,RunLoop会立马退出

runLoop的作用

1.保持程序的持续运行

2.处理app中的各种事件:比如触摸事件、定时器事件.其他系统事件

3.节省CPU资源,提高程序性能,有事情就做事情,没事情就休息

怎样创建一个常驻子线程(代码片段中有具体实现)

1、为当前线程创建一个runloop

2、向runloop中添加Port/Source等维持RunLoop的事件循环(注意:如果runloop的mode中一个item都没有,runloop会退出的) 3、启动该runloop

runloop 和runtime的区别

  • 1.在oc中runloop实际是一个用来管理需要处理的事件和消息的对象。

    一个runloop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件, 而使用runloop的目的是让线程在有工作的时候忙于工作,而在没工作的时候出于休眠状态。

  • 2.runtime是一种机制,又叫运行时,是指将一些决定从编译期推迟到代码运行期来处理,runtime底层由c语言实现

在oc中所有的一切都是对象,所以runtime机制就是说;只有在运行时才能真正确定对象的相关信息,故我们利用runtime机制可以在代码运行时获取并修改类的相关信息,比如获取类的方法列表,属性列表,添加方法.属性等。

怎样保证子线程数据回来时刷新主线程UI的时候不打断用户的滑动操作?

可以把刷新的操作放在主线程上并将RunLoop设置为NSDefaultRunLoop的模式上即可,这样就会等用户不在滑动,并且手指离开的时候才执行刷新操作了 因为滑动时主现场的runloop为UITrackingRunLoopMode,不滑动时为NSDefaultRunLoopMode。

为什么Main函数不会退出

就是因为UIApplicationMain内部默认开启了一个runloop,并且执行了一段无限循环的代码,(注意这里的无限循环,不是简单的for或者while循环),因为一直在无限循环里,所以这个函数永远不会被返回,而是不断的接收消息/事件以及等待休眠,所以程序运行之后会保持运行状态不会退出

NSTimer与Runloop及线程的关系加 滚动试图,线程注意点

  • 从创建方式来说:
    1. timerWithTimeInterval;创建的timer不会自动添加到当前线程的runloop中,需要手动加入
  1. scheduledTimerWithTimeInterval 创建的timer会自动添加到当前线程的runloop中。
  • timer在主线程时

    存在scrollview需要指定model为track(UITrackingRunLoopMode)或者common(NSRunLoopCommonModes)

  • timer在子线程,加入runloop然后启动即可

    有scrollview切换mode的原因是:

    存在scrollview。在点击UIScorllview的区域时,mode是UITrackingRunLoopMode, 但若定时器器的model是 NSDefaultRunLoopMode会停⽌止工作。

Runloop的⽣生命周期:

在第⼀一次获取时创建,在线程结束时销毁

source1与source0

通过source1捕捉系统事件,然后打包成source0这个系统触摸事件分发给app

为什么Runloop并不是由系统自动控制的

因为主线程会默认启动runloop,但子线程不会自动启动runloop,故runloop并不是由系统自动控制的.

Event Loop(消息循环)

就是do while死循环。这种机制的关键点就是如何管理事件/消息。比如;如何让在没有消息的时候线程休眠来避免资源占用,和在有消息是即时处理消息。runloop就是对它的优化。本质是一样的。

runloop的集中状态

1.进入runloop循环

2.即将处理time事件

3.即将处理source事件

4.即将休眠

5.结束休眠

JSRUN前端笔记, 是针对前端工程师开放的一个笔记分享平台,是前端工程师记录重点、分享经验的一个笔记本。JSRUN前端采用的 MarkDown 语法 (极客专用语法), 这里属于IT工程师。