iOS RunLoop(一)

级别: ★★☆☆☆
标签:「iOS」「RunLoop」「线程常驻」
作者: 陈彬
审校: QiShare团队

前言:
这篇文章主要内容是介绍RunLoop的一些概念以及用法:使用RunLoop创建常驻线程、自定义输入源进行线程通信等。同时借此机会希望能够和大家一起讨论RunLoop相关的知识,加深对RunLoop的理解。

一、RunLoop是什么?

RunLoop是与线程相关的基础架构中的一部分,它是一个处理事件的循环(线程进入这个循环,运行事件处理程序来响应传入的事件),RunLoop的目的是当有事件需要处理时,线程是活跃的、忙碌的,当没有事件后,线程进入休眠。

RunLoop结构以及事件来源:

一个RunLoop包含若干个Mode,每个Mode包含若干个Source/Timer/Observer/Port。当启动一个RunLoop时会先指定一个Mode,检查指定Mode是否存在以及Mode中是否含有SourceTimer,如果Mode不存在或者Mode中无SourceTimer,认为该Mode是一个空的ModeRunLoop就直接退出。

Input Source:
  • Port-Based Sources:监听AppMach Port,由内核发出信号,输入源收到信号后,执行相关的例程。

  • Custom Input Sources:监听自定义的输入源,需要在其它线程手动发送信号,输入源收到信号后,执行相关的例程。

  • Cocoa Perform Selector Sources:Cocoa中自定义的输入源,目的是在不同线程中执行任务,同一线程中的任务是顺序执行的,当任务执行完成后系统会自动移除这个源。(注意:在目标线程中执行任务时,这个目标线程必须有活跃的RunLoop

Timer Source:

时间源会在预设的时间同步传递事件给对应的线程,计时器是线程通知自己做某事的一种方式。

计时器并不是真正的实时的,当计时器未处于RunLoop当前监听的Mode,那么计时器是不会计时调度任务的,只有RunLoop当前监听的Mode是计时器关联的Mode时,计时器才会开始执行任务,例如:NSTimer添加至主线程RunLoopDefaultMode中,此时滑动TableView/ScrollView时,RunLoop会切换至TrackMode,计时器是不会调度任务的。

如果RunLoop在执行一个例程时,计时器触发了,那么计时器会等待RunLoop将该例程执行完成,在下一次的循环中处理。在RunLoop未运行情况下,计时器永远不会触发任务。

二、RunLoop怎么使用?

应用启动时,会自动在主线程上设置运行RunLoop,所以不需要在主线程上显示的启动RunLoop,无需调用[[NSRunLoop currentRunLoop] runUntilDate:]这些方法。那么如果我们显示的在主线程中调用RunLooprun方法会出现什么结果呢?通过Demo中显示,主线程中显示启动RunLoop会影响当前事件处理,但是由于RunLoop并没有停止,所以其他事件能够正常接收和处理。

而子线程也不并是必须要设置运行RunLoop才能执行任务,比如说只是简单在子线程中处理个耗时任务等,如下场景是需要启动RunLoop的:

  1. 使用NSPort或者自定义输入源与其它线程通信。
  2. 在线程上使用计时器。
  3. 在一个Cocoa应用中使用performSelector相关方法。
  4. 使线程常驻,在该线程定期执行任务。

正如前言中所说,本文主要说明线程常驻和自定义输入源线程通信。

线程常驻:

方式一:无条件的启动RunLoop是最简单的选择,但它也是最不可取的选择,它会将线程置于永久循环中,这样几乎无法控制RunLoop本身,虽然可以添加和删除输入源和计时器,但停止RunLoop的唯一方法是杀死RunLoop。(以上内容是通过Google翻译的官网内容可能理解有些偏差届时还望指正,事实上我在做实验的过程中,发现使用NSThreadcancel方法是无法停止RunLoop的,cancel方法是更改线程的取消状态,指示它应该退出。在当前线程下执行[NSThread exit]方法,退出了该线程,但demo中的LongLifeThreadViewController仍然未被释放)

方式二:启动RunLoop时设定时限,RunLoop将一直运行直到事件到达或分配的时间到期。如果事件到达,则将该事件分派给处理程序进行处理,然后退出此次RunLoop。可以通过重新启动RunLoop处理下一个事件。同样如果分配的时间到期,也可以重新启动RunLoop来处理。这种方式可以指定RunLoopMode,官网力荐。

自定义输入源线程通信:

定义输入源:

  1. 提供输入源要处理的信息。
  2. 接收到事件时的执行例程。
  3. 输入源加到RunLoop时的执行例程。
  4. 输入源失效时的执行例程。

个人感觉可以根据个人需求决定是否实现第3、4两条内容。(注意定义输入源只能通过CoreFoundation提供的对应API实现,其中的回调例程由C语言实现)

RunLoop上安装输入源:如果实现了上述的第3条内容时,将自定义的输入源添加到RunLoop时,就会回调输入源对应的schedule实现例程。

向输入源发送信号:输入源在接收到信号后,会执行对应的perform例程,perform例程就是对应事件处理程序。(注意如果线程处于休眠状态,要唤醒线程,否则该事件无法被处理。


结语:
关于RunLoop的内容还有很多,比如:RunLoopModesRunLoopObserverNSPortNSTimer等等,当然还有RunLoop的源码,这些内容在此并未列出,如有感兴趣的小伙伴可以先行花时间去探索、学习,到时可以一起交流、讨论。

源码地址:QiRunLoopDemo1


推荐文章:
iOS 常用调试方法:LLDB命令
iOS 常用调试方法:断点
iOS 常用调试方法:静态分析
iOS消息转发
iOS 自定义拖拽式控件:QiDragView
iOS 自定义卡片式控件:QiCardView
iOS Wireshark抓包
iOS Charles抓包

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349