美文网首页程序员
Runloop是什么?

Runloop是什么?

作者: 海绵宝宝不要哭 | 来源:发表于2016-05-07 00:58 被阅读359次

    从子面理解

    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是什么?

        本文链接:https://www.haomeiwen.com/subject/gyidrttx.html