RunLoop理解✨

  • 版权声明:本文为博主原创文章,未经博主允许不得转载。

一. Runloop的基本知识

1. 概念
Runloop是运动循环,不断跑圈,无限循环.
RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,这篇文章将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理。之后会介绍一下在 iOS 中,苹果是如何利用 RunLoop 实现自动释放池、延迟回调、触摸事件、屏幕刷新等功能的。
  • 作用:
保持程序的持续运行 (iOS程序一直活着的原因)

处理App中的各种事件(eg:触摸事件/定时器事件/selector事件[选择器·performSelector···])

节省CPU资源,提高程序的性能(有事做事,没事休息)

程序已启动,就开启了一个runloop无限循环,因此程序才能持续的运行
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://upload-images.jianshu.io/upload_images/838345-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://upload-images.jianshu.io/upload_images/838345-f15d99e192b2398a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
注意:
![](http://upload-images.jianshu.io/upload_images/838345-5ed898f1141c64c7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



- 5.Runloop运行逻辑
![](http://upload-images.jianshu.io/upload_images/838345-0e9a4fa01684f71d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://upload-images.jianshu.io/upload_images/838345-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/)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容