Runloop(运行循环)是什么?

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

今天整理一下运行循环来帮朋友们了解一下什么是运行循环,也叫消息循环,建议大家称之为运行循环(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秒钟之后,子线程的运行循环就会退出。

希望能帮到大家!

时间: 2024-10-14 08:50:57

Runloop(运行循环)是什么?的相关文章

Runloop 运行循环

什么是RunLoop 运行循环 一个线程对应一个RunLoop,主线程的RunLoop默认已经启动,子线程的RunLoop得手动启动(懒加载, 调用currentRunLoop方法) RunLoop只能选择一个Mode启动,如果当前Mode中没有任何Source(Sources0.Sources1).Timer,那么就直接退出RunLoop RunLoop作用 保持程序的持续运行 处理App中的各种事件(比如触摸事件.定时器事件.Selector事件) 节省CPU资源,提高程序性能:该做事时做事

RunLoop运行循环机制

http://www.jianshu.com/p/0be6be50e461 基本概念 进程 进程是指在系统中正在运行的一个应用程序,而且每个进程之间是独立的,它们都运行在其专用且受保护的内存空间内,比如同时打开迅雷.Xcode,系统就会分别启动两个进程. 线程 一个人进程如果想要执行任务,必须得有至少一条线程,进程的所有任务都会在线程中执行,比如使用网易云音乐播放音乐,使用迅雷下载电影,都需要在线程中执行. 主线程 iOS 程序运行后,系统会默认开启一条线程,称为“主线程”或者“UI 线程”,主

RunLoop(运行循环)-002-加载大图

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "Yuanti SC"; color: #ff2600; background-color: #ffffff } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "Yuanti SC"; color: #008400; background-color: #ffffff } p.p3 { margin:

IOS 开发笔记-基础 UI(9)运行循环的概念

运行循环 int i = 0; // 死循环 while (YES) { printf("请输入一个整数,0表示退出:"); scanf("%d", &i); NSLog(@"%d", i); if (i == 0) { break; } } 以上程序,会不停的循环运行,但是,会在输入的时候中断,等待,有了输入之后,再继续循环运行,且一旦输入了复合条件的值,那么通过 if 判断,break退出循环体. 这就是简单的 runloop 模型.

iOS开发 底层抛析运行循环—— RunLoop

http://blog.csdn.net/zc639143029/article/details/50012527 一.RunLoop基本概念 概念:程序的运行循环,通俗的来说就是跑圈. 1. 基本作用(作用重大) (1) 保持程序的持续运行(ios程序为什么能一直活着不会死) (2) 处理app中的各种事件(比如触摸事件.定时器事件[NSTimer].selector事件[选择器·performSelector···]) (3)节省CPU资源,提高程序性能,有事情就做事情,没事情就休息 2.

运行循环(Run Loops)

运行循环是与线程相关的基础工具的一部分.运行循环是一个用来安排工作并协调传入事件接收的一个事件处理循环.运行循环的目的是当需要工作的时候,让你的线程处于忙碌状态:当没有工作时,让你的线程处于睡眠状态. 运行循环管理并不是完全自动运行,你必须设计线程代码在适当的时间启动运行循环并响应传入的事件.Cocoa和核心基础提供运行循环对象来帮助你配置和管理你的线程运行循环.你的引用不需要显式的创建这些对象,每个线程,包括应用的主线程都有一个关联的运行循环对象.然而,只有次要线程需要显式的运行他们的运行循环

运行循环

程序启动就是有一个运行循环,监听系统中的所有事件 运行有两种模式(从代码来看) NSDefaultRunLoopMode(默认,用户普通点击) NSRunLoopCommonModes(滚动) 一旦发现有滚动事件,默认模式暂时不监听 Timer,(是一个没地位的,) 如果cpu在做大规模运算,cup没时间打理Timer,Timer就闲下来不执行,和下一次一起执行,任务的叠加 Timer,通常用来有一定时间跨度的处理周期性事件,所以不是准确,可以用多线程处理 CADdisplaylink

NSTimer与运行循环

NSTimer准确吗?如果不准确,怎么办? 通常用来有一点时间跨度的周期性事件的处理! CDADisplayLink 1 // 2 // HMViewController.m 3 // 08-倒计时 4 // 5 // Created by apple on 14-8-18. 6 // Copyright (c) 2014年 itcast. All rights reserved. 7 // 8 9 #import "HMViewController.h" 10 11 @interfa

主运行循环

主运行循环负责处理所有跟用户操作相关的事件,主运行循环在程序启动时被 UIApplication 对象创建,运行在主线程上,用来处理事件和更新基于View的UI. 当用户与设备交互时,操作系统生成相关的事件,然后通过一个由 UIKit 创建的端口,交给App.事件先加入事件队列,然后一个一个的交给主运行循环去处理.UIApplication 对象是第一个接收到事件的对象. 大部分类型的事件会交给App.但是有些事件不会,比如加速度计事件会直接交给定义的加速度代理对象去处理. 主运行循环