Runloop是什么?

从子面理解

Run:跑
loop:环

所以可以理解为
  • 1:运行循环
  • 2:跑圈
图形解释
运行循环
基本作用
  • 保持程序的持续运行
  • 处理APP中的各种事件(比如触摸事件;定时器事件;Selector事件)
  • 节省CPU的资源,提高程序的性能:也就是该做事的时候做事,不该做事的时候休息。
  • ……
APP中的分析

1:为什么我们的APP可以持续的运行?
2:为什么可以让APP可以处理我们的某些事件?

我们从一个最简单的APP入口动手

  • 1:APP的入口main函数中
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

1:分析main函数

  • return UIApplicationMain
    -这里返回的UIApplicationMain,也就是主线程,这里面具体他做了一些什么?

其实就是创建了一个主线程的Runloop对象,这个Runloop对象,可以让我们程序持续的运行,也就是说,我们main这里的大括号,一直都不会退出,大家可以理解为开启了一个死循环。

可以理解为如下:

  • Runloop存在的情况下
    程序有Runloop的情况下

由于main函数里面启动了一个Runloop,所以程序并不会立马退出,可以保存程序的持续的运行。

  • Runloop不存在的情况下
    Runloop不存在的情况下

没有Runloop的情况下第三行程序运行就结束了

  • main函数中
Xcode为我们生成的main函数

第14行代码UIAPPlicationMain函数内部就启动了一个Runloop

  • 所有的UIAPPlicationMain函数一直没有返回,保持了程序的持续运行。
  • 这个默认启动的Runloop是跟主线程相关联的。
结论,我们程序的持续运行的原因是因为有了Runloop的这个对象。

接下来我们研究Runloop对象。

  • 首先iOS中有两套API来访问和使用Runloop
  • Foundation
    NSRunloop
  • core Foundation
    CFRunloopRef

1:NSRunloopCFRunloopRef都是代表着Runloop对象。
2:NSRunloop是基于CFRunloopRef的一层objective-c包装,所以要了解我们的Runloop,我们需要去多研究CFRunloopRef层面的API

(http://opensource.apple.com/source/CF/CF-1151.16/ "CFRunloopRef开源资料")

我们之前是看到了,在程序的主线程中自动启动了一个与之关联的Runloop,那么线程与Runloop对象的关系到底是怎么样的呢?

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSLog(@"%p %p",[NSRunLoop currentRunLoop],[NSRunLoop mainRunLoop]);   
}
  • 我们打印currentRunloop以及mainRunloop的内存地址指针
主线程的当前```Runloop```对象以及主```Runloop```对象
  • 可以看得到,他们的内存地址指针是一样的。

我们接下来去子线程里面看一下,一条陌生的子线程和Runloop的关系

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    NSLog(@"%p %p",[NSRunLoop currentRunLoop],[NSRunLoop mainRunLoop]);
    
    NSThread *thred = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
    [thred start];
    
}
-(void)run{
    
    //自己创建的子线程,是没有自动创建一个runloop对象的,只有主线程才会默认的创建一个runloop
    NSLog(@"%p",[NSRunLoop currentRunLoop]);
}
  • 我们创建一条子线程,并且获取了他的一个currentRunloop

注意:Runloop对象的创建不是使用alloc以及init来创建,而是使用获取currentRunloop来创建,其实内部就是一个懒加载,在你第一次调用的时候便给你创建Runloop对象,并且给到你当前的线程.

  • 打印结果
创建一条子线程且为他创建一个Runloop对象

我们可以看得到,开启的那条子线程中的Runloop对象的地址指针和我们之前在viewDidLoadRunloop的内存地址指针是不一样的。

此时可能会想,是否是一条线程就有一条与之对应且唯一的一个Runloop对象。我们去到CFRunloopRef的开源代码去分析他。
(http://opensource.apple.com/source/CF/CF-1151.16/ "CFRunloopRef开源资料")

去到其中CFRunloop

我们可以看到很多开源的头文件

打开源码,我们可以看到这个函数的声明

```CFRunloopRef```内部源码

结论

  • 主线程的Runloop已经自动创建好了,子线程的Runloop需要主动去创建
  • 每条线程都有唯一的一个与之对应Runloop对象
  • Runloop在第一次获取时创建,在线程结束时销毁。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Runloop就像一台引擎,它控制着程序的运行。图为GENX发动机在加拿大温尼伯进行寒冷天气测试, 序言 做iOS...
    AKTeamYang阅读 2,823评论 0 13
  • Run loop 剖析:Runloop 接收的输入事件来自两种不同的源:输入源(intput source)和定时...
    Mitchell阅读 12,538评论 17 111
  • Event Loop 模型 如果我们需要一个机制, 让线程能随时处理事件但并不退出, 通常的代码逻辑是这样: 这就...
    Stago阅读 724评论 0 0
  • 一、什么是runloop 字面意思是“消息循环、运行循环”。它不是线程,但它和线程息息相关。一般来讲,一个线程一次...
    WeiHing阅读 8,203评论 11 111
  • 前言 最近离职了,可以尽情熬夜写点总结,不用担心第二天上班爽并蛋疼着,这篇的主角 RunLoop 一座大山,涵盖的...
    zerocc2014阅读 12,448评论 13 67