RunLoop

作者: 请叫我周小帅 | 来源:发表于2017-04-17 15:02 被阅读1次

    runloop从字面意思就是运行循环,跑圈。


    runloop基本作用:

    *保持程序的 持续运行

    *处理App种的各种事件,比如触摸时间、定时器事件、Selector事件。

    *节省CPU资源,提高程序性能:该做事时做事,该休息时休息。

    *。。。。。。


    如果说没又runloop的话,那么程序就会立即结束,代码运行到第三行程序就结束。

    1.intmain(intargc,char*argv[]) {

    2.NSLog(@"ZhouXiaoShuai");

    3.return 0;

    4.}


    有RunLoop的话,main函数里面启动了RunLoop,那么程序并不会马上退出,保持持续运行状态。

    1.intmain(intargc,char*argv[]) {

    2.BOOLrunning =YES;

    3.do{

    4.//执行各种任务,处理各种事件

    5.// ......

    6.}while(running);

    7.return 0;

    8.}

    main函数种的RunLoop

    第14行代码的UIApplicationMain函数内部就启动了一个RunLoop,所以UIApplicationMain函数一直没有返回,保持了程序的持续运行,这个默认启动的RunLoop是跟主线程相关联的。


    iOS中想访问和使用RunLoop的话有两套API

    Foundation中的NSRunLoop

    Core Foundation中的CFRunLoopRef

    NSRunLoop和CFRunLoopRef都代表着RunLoop对象

    NSRunLoop是基于CFRunLoopRef的一层OC包装,所以要了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API(Core Foundation层面)

    RunLoop与线程

    每条线程都有唯一的一个与之对应的RunLoop对象。

    主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建。

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


    Foundation

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

    [NSRunLoop mainRunLoop];             //获得主线程的RunLoop对象

    Core Foundation

    CFRunLoopGetCurrent();                   //获得当前线程的RunLoop对象

    CFRunLoopGetMain();                       //获得主线程的RunLoop对象


    RunLoop相关类

    CoreFoundation中关于RunLoop的5个类

    CFRunLoopRef

    CFRunLoopModeRef

    CFRunLoopSourceRef

    CFRunLoopTimerRef

    CFRunLoopObserverRef



    CFRunLoopModeRef

    CFRunLoopModeRef代表RunLoop的运行模式。

    一个RunLoop包含若干个Mode,每个Mode又包含若干个Source/Timer/Observer。

    每次RunLoop启动时,只能指定其中一个Mode,这个Mode被称作CurrentMode。

    如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入,这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响。


    CFRunLoopModeRef

    系统默认注册了5个Mode:

    kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行。

    UITrackingRunLoopMode:界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode影响。

    UIInitializationRunLoopMode:在刚启动App时第进入的第一个Mode,启动完成后就不再使用。

    GSEventReceiveRunLoopMode:接受系统事件的内部Mode,通常用不到kCFRunLoopCommonModes:这是一个占位用的Mode,不是一种真正的Mode。


    CFRunLoopSourceRef

    CFRunLoopSourceRef是事件源(输入源)

    以前的分法

    Port-Based Sources

    Custom Input Sources

    Cocoa Perform Selector Sources

    现在的分法

    Source0:非基于Port的

    Source1:基于Port的


    CFRunLoopTimerRef

    CFRunLoopTimerRef是基于时间的触发器

    基本上说的就是NSTimer


    CFRunLoopObserverRef

    CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变,可以监听的时间点有以下几个。


    RunLoop处理逻辑-官方版


    RunLoop处理逻辑-官方版

    RunLoop的事件队列:

    每次运行runloop,你线程的runloop对会自动处理之前未处理的消息,并通知相关的观察者,具体的顺序如下:

    1.通知观察者run loop已经启动。

    2.通知观察者任何即将要开始的定时器。

    3.通知观察者任何即将启动的非基于端口的源。

    4.启动任何准备好的非基于端口的源。

    5.如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。

    6.通知观察者线程进入休眠。

    7.将线程置于休眠直到下面的事件发生:

            - 某一事件达到基于端口的源。

            - 定时器启动。

            - RunLoop设置的时间已经超时。

            - RunLoop被显式唤醒。

    8.通知观察者线程将被唤醒。

    9.处理未处理的事件

             - 如果用户定义的定时器启动,处理定时器事件并重启runloop   进入步骤2

             - 如果输入源启动,传递相应的消息。

             - 如果runloop被显式唤醒而且时间还没超时,重启runloop   进入步骤2

    10.通知观察者runloop结束。


    RunLoop处理逻辑

    相关文章

      网友评论

          本文标题:RunLoop

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