RunLoop理解✨

作者: LeaderBiao | 来源:发表于2016-06-28 19:10 被阅读71次
    • 版权声明:本文为博主原创文章,未经博主允许不得转载。
    2.RunLoop对象
    1. 在iOS开发中有两套api来访问Runloop
        Foundation框架 [NSRunloop](OC)
    
        Core Foundation框架 [CFRunloopRef](C)```
    
    2. NSRunLoop和CFRunLoopRef都代表着RunLoop对象,它们是等价的,可以互相转换
    
    3. NSRunLoop是基于CFRunLoopRef的一层OC包装,所以要了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API(Core Foundation层面)
    
    
    ######3.Runloop与线程的关系
    
    1.Runloop和线程的关系:一个Runloop对应着一条唯一的线程
    
        问题:如何让子线程不死
    
        回答:给这条子线程开启一个Runloop
    
    2.Runloop的创建:主线程Runloop已经创建好了,子线程的runloop需要手动创建
    
    3.Runloop的生命周期:在第一次获取时创建,在线程结束时销毁
    
    ###二. Runloop对象的创建
    
    1. Foundation框架\[NSRunloop]创建Runloop对象
    
    // 获取当前线程下的Runloop, 懒加载的形式创建
     NSRunLoop * runloop1 = [NSRunLoop currentRunLoop];
    // 获取主线程下的Runloop
    NSRunLoop * runloop1 = [NSRunLoop mainRunLoop];```
    
    1. Core Foundation框架[CFRunloopRef]创建Runloop对象
        // 获取当前线程下的Runloop, 懒加载的形式创建
        CFRunLoopRef runloop2 = CFRunLoopGetCurrent();
        // 获取主线程下的Runloop
        CFRunLoopRef runloop2 = CFRunLoopGetMain();```
    
    3. Runloop运行原理图
    ![图片来自官网](http:https://img.haomeiwen.com/i838345/faae7ec4a5fb10db.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    
    4.Runloop相关的类
    
    
    CFRunLoopRef
    
    CFRunloopModeRef [Runloop的运行模式]
    
    CFRunloopSourceRef [Runloop要处理的事件源]
    
    CFRunloopTimerRef [Timer事件]
    
    CFRunloopObserverRef [Runloop的观察者(监听者)]```
    
    Runloop要想跑起来,它的内部必须要有一个mode,mode中必须有source/observer/time,至少要有其中的一个.

    5.CFRunloopModeRef [Runloop的五个运行模式]

        Runloop每次启动的时候只能指定一个运行模型,切换模式时必须退出当前的Runloop,再重新进入一个mode,是为了分割不同组的定时器互不影响
    
        kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
    
        UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
    
        UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
    
        GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
    
        kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode
    

    6.CFRunloopTimerRef [Timer事件]

    • 1.Timer事件


    • 2.GCD定时器
      GCD定时器必须必须保存起来才能使用
        - (void)gcdTimer
        {
         NSLog(@"+++++++++");
         // 1.创建定时器
         dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
         
         // 2.设置定时器
         /*
             第一个参数:定时器
             第二个参数:从哪个时间开始
             第三个参数:间隔时间
             第四个参数:精确度, 0代表无误差
             */
            dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
         
         // 3.定时器触发事件
            dispatch_source_set_event_handler(timer, ^{
         NSLog(@"----------");
         });
         
         // 4.开启定时器
            dispatch_resume(timer);
         
         // GCD定时器创建是个局部变量需要保存才能执行
            self.timer = timer;
        }```
    
    
    - 3.CFRunloopSourceRef [Runloop要处理的事件源]
    
    (1)以前的分法
    ```swift
    Port-Based Sources
    
    Custom Input Sources
    
    Cocoa Perform Selector Sources```
    
    
    (2)现在的分法
    
    ```swift
    Source0:非基于Port的 (用户触发的时间)
    
    Source1:基于Port的 (通过内核和其它线程相互发送消息)```
    
    
    - 4.CFRunloopObserverRef [Runloop的观察者 (监听者)]
    ![](http:https://img.haomeiwen.com/i838345/f15d99e192b2398a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    注意:
    ![](http:https://img.haomeiwen.com/i838345/5ed898f1141c64c7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    
    
    - 5.Runloop运行逻辑
    ![](http:https://img.haomeiwen.com/i838345/0e9a4fa01684f71d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ![](http:https://img.haomeiwen.com/i838345/a917e5bd50943a4c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    
    ###iOS中的RunLoop
    
    >Runloop是事件接收和分发机制的一个实现。
    
        Runloop提供了一种异步执行代码的机制,不能并行执行任务。
    
        在主队列中,Main RunLoop直接配合任务的执行,负责处理UI事件、定时器以及其他内核相关事件。
    
    >RunLoop的主要目的:
    
        保证程序执行的线程不会被系统终止。   
    
    >什么时候使用RunLoop ?
    
        当需要和该线程进行交互的时候才会使用Runloop.
    
        每一个线程都有其对应的RunLoop,但是默认非主线程的RunLoop是没有运行的,需要为RunLoop添加至少一个事件源,然后去run它。
    
        一般情况下我们是没有必要去启用线程的RunLoop的,除非你在一个单独的线程中需要长久的检测某个事件。
    
        主线程��默认有Runloop。当自己启动一个线程,如果只是用于处理单一的事件,则该线程在执行完之后就退出了。所以当我们需要让该线程监听某项事务时,就得让线程一直不退出,runloop就是这么一个循环,没有事件的时候,一直卡着,有事件来临了,执行其对应的函数。
    
        Runloop,正如其名所示,是线程进入和被线程用来响应事件以及调用事件处理函数的地方。需要在代码中使用控制语句实现run loop的循环,也就是说,需要代码提供while 或者 for循环来驱动run loop。
    
        在这个循环中,使用一个Runloop对象[NSRunloop currentRunloop]执行接收消息,调用对应的处理函数。
    
        Runloop接收两种源事件:input sources和timer sources。
    
        input sources 传递异步事件,通常是来自其他线程和不同的程序中的消息;
    
        timer sources(定时器) 传递同步事件(重复执行或者在特定时间上触发)。
    
        除了处理input sources,Runloop 也会产生一些关于本身行为的notificaiton。注册成为Runloop的observer,可以接收到这些notification,做一些额外的处理。(使用CoreFoundation来成为runloop的observer)。
    
    >Runloop工作的特点:
    
        1> 当有事件发生时,Runloop会根据具体的事件类型通知应用程序作出响应;
    
        2> 当没有事件发生时,Runloop会进入休眠状态,从而达到省电的目的;
    
        3> 当事件再次发生时,Runloop会被重新唤醒,处理事件。
    
    >提示:一般在开发中很少会主动创建Runloop,而通常会把事件添加到Runloop中。
    
    ####参考:
    [官方文档](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW47)
    [深入理解RunLoop](http://blog.ibireme.com/2015/05/18/runloop/)

    相关文章

      网友评论

        本文标题:RunLoop理解✨

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