运行循环是什么?从介绍到演示

今天整理一下运行循环来帮朋友们了解一下什么是运行循环,也叫消息循环,建议大家称之为运行循环(Runloop).


===

关于多线程的运行循环(消息循环)

1. 什么是运行循环

(1)Runloop就是运行循环,每个线程内部都有一个运行循环.

(2)只有主线程的运行循环默认是开启的,子线程的运行循环.

2. 运行循环的作用

(1)保证程序不退出,iOS的应用程序启动之后,之所以不会退出,就是因为有Runloop(运行循环).运行循环是一个死循环,只有满足一定条件才会结束循环.

(2)负责处理输入事件

(3)如果没有事件发生,会让程序进入休眠状态.

3.输入事件

Runloop接收的事件来自两种不同的来源:输入源 和 定时源.

(1)输入源(Input sources)输入源传递异步事件,通常消息来自于其他线程或程序。

(2)定时源(Timer sounces)定时源则传递同步事件,发生在特定时间或者重复的时间间隔。两种源都使用程序的某一特定的处理例程来处理到达的事件。

(3)下图展示了运行循环的概念结构以及事件来源的种类:
输入源能够通过runUntilDate 方法使线程退出;定时源不能使线程退出.

runloop.png

4.运行循环的模式

运行循环模式是输入源和定时源的一个集合,这个集合会被监听.

每次启动运行循环,可以指定一个特殊的模式,在运行循环执行期间,只有跟特定的模式相关联的事件源才会被监听以及允许传递它们的事件。跟其它模式相关联的事件源将不会被监听。因此,可以通过运行循环来过滤掉一些不期望的事件

下图是系统定义的几种运行循环模式:

Mode Name Description
Default NSDefaultRunLoopMode(Cocoa)kCFRunLoopDefaultMode (Core Foundation) The default mode is the one used for most operations. Most of the time, you should use this mode to start your run loop and configure your input sources.
Connection NSConnectionReplyMode(Cocoa) Cocoa uses this mode in conjunction with NSConnection objects to monitor replies. You should rarely need to use this mode yourself
Modal NSModalPanelRunLoopMode(Cocoa) Cocoa uses this mode to identify events intended for modal panels.
Event tracking NSEventTrackingRunLoopMode(Cocoa) Cocoa uses this mode to restrict incoming events during mouse-dragging loops and other sorts of user interface tracking loops.
Common modes NSRunLoopCommonModes(Cocoa)kCFRunLoopCommonModes (Core Foundation) This is a configurable group of commonly used modes. Associating an input source with this mode also associates it with each of the modes in the group. For Cocoa applications, this set includes the default, modal, and event tracking modes by default. Core Foundation includes just the default mode initially. You can add custom modes to the set using theCFRunLoopAddCommonMode function.

大致的意思是指:

(1)Default: default模式可以用于大多数操作。在大多数时间,应该使用这种模式来启动和设置输入源。

(2)Connection: Cocoa使用这种模式联合NSConnection对象来监听响应。我们很少会自己用到这种模式

(3)Modal: Cocoa使用这种模式来识别为模态面板准备的事件。

(4)Event tracking: Cocoa使用这种模式来约束鼠标拖拽或其它用户界面追踪循环的事件。

(5)Common modes: 这是一个通用的模式组,使用这种模式关联输入源,同样会关联这个模式组里面的每一种模式。对于Cocoa应用来说,这个集合包含了 default、modal以及event tracking模式。
Core Foundation初始状态下只包含 default 模式,但是可以
通过 CFRunLoopAddCommonMode函数来添加自定义模式。

5.通过定时器演示运行循环的模式

注意:定时器执行的方法中不宜执行太耗时的操作,否则会降低用户体验.

  • 第一步:创建定时器
    在viewDidLoad方法中:
//1,创建定时器
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:
self selector:@selector(demo) userInfo:nil repeats:YES]; 
//demo方法
- (void)demo {
        NSLog(@"hello");
}
  • 第二步:将定时器添加到当前线程的运行循环
//将定时器添加到当前线程的运行循环
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

===

注意:这里的模式对应的是输入事件(定时器timer)的模式.

  • 第三步:运行程序,执行结果如下:
屏幕快照 2016-03-12 下午9.54.24.png
当程序运行起来之后,打印输出会按照定时器,每秒输出一次.但是,如果拖动界面的控件,打印输出就会停止(即不再打印输出).
思考:为什么?
  • 第四步: 打印当前运行循环的模式

demo方法中:

NSLog(@"---%@", [NSRunLoop currentRunLoop].currentMode);

执行程序:

屏幕快照 2016-03-12 下午9.58.52.png

注意:[NSRunLoop currentRunLoop].currentMode 中的模式对应的是运行循环的模式。

结论:
运行循环是在一个指定的模式下运行的(默认是NSDefaultRunLoopMode),设置的输入事件也需要指定一个模式,运行循环的模式必须和输入事件的模式相匹配才会执行。
一开始,输入事件模式是NSDefaultRunLoopMode,运行循环默认也是NSDefaultRunLoopMode,所以可以正常输出结果。
拖动控件,之所以不会打印输出,就是因为运行循环的模式发生了改变,变成了 UITrackingRunLoopMode,这个时候二者模式不匹配,所以不能正常输出。

总结:

(1)运行循环是在一个指定的模式下运行的,输入事件也有对应的模式,只有当二者的模式相匹配,对应的方法才会执行。

(2)运行循环模式:
1> 运行循环启动后,默认模式为 NSRunLoopDefaultMode
2> 如果滚动scrollView,运行循环模式为 UITrackingRunLoopMode。

子线程的运行循环

主线程的运行循环默认是开启的,子线程的运行循环默认是不开启的。
//第一步: 创建子线程
viewDidLoad方法中: 
    // 创建子线程
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];
    [thread start];
//第二步: 往子线程的运行循环添加输入源
// 往子线程的运行循环上添加输入源
    [self performSelector:@selector(demo1) onThread:thread withObject:
nil waitUntilDone:NO];
// 执行在子线程的方法
- (void)demo {
     NSLog(@"I'm running");
}
// 执行在子线程的运行循环中的方法
- (void)demo1 {
-   NSLog(@"I'm running on runloop");
}
第三步: 开启子线程的运行循环
- (void)demo {
    NSLog(@"I'm running");
    // 这些数入源能够防止运行循环退出, 即 只要有数入源, run 方法启动的运行循环就不会退出
    // Those sources could therefore prevent the run loop from exiting.
[[NSRunLoop currentRunLoop] run];
NSLog(@"end");
}
然后执行程序得到以下结果:

屏幕快照 2016-03-12 下午10.05.45.png

由输出结果可知: 没有打印 end,即只要有输入源,使用run方法启动的运行循环不会退出。

第五步: 通过 runUntilDate来启动运行循环

// 2秒钟之后消息循环结束

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];

这样的话,2秒钟之后,子线程的运行循环就会退出。

希望能帮到大家!

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

推荐阅读更多精彩内容