美文网首页
iOS-RunLoop

iOS-RunLoop

作者: 自律_自强_通达 | 来源:发表于2020-10-19 22:57 被阅读0次

iOS-RunLoop

一、RunLoop简介

RunLoop字面意思运行循环(跑圈),在我们的项目也就是一个死循环(充满灵性的)。为什么说他是充满灵性的死循环呢?因为他可以在我们需要的时候自己跑起来运行,在我们没有操作的时候就停下来休息,这样就能够充分节省CPU资源提高程序的性能。

二、RunLoop基本作用:

  1. 保持程序持续运行,程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不被销毁,也就保证了程序的持续运行。
  2. 处理APP中的各种事件,(如:触摸事件,定时事件,Selector事件等)。
  3. 节省CPU资源,提高程序性能,程序运行起来时,当什么操作都没有的时候,RunLoop就会告诉CPU,现在没事情做,我要去休息。这时候CPU就会将其资源释放出来去做其他事情,当有事情要做RunLoop就会立马去做事情。我们通过下图了解RunLoop内部运行原理
RunLoop原理图.png

通过图片可以看出,RunLoop在跑圈过程中,当收到Input sources或者Timer sources的时候就会交个对应的方法去处理。当没有事件消息传入的时候,RunLoop就会休息了,这里只是简单的理解这张图。接下来我们来了解RunLoop对象和一些相关类,来更深入的了解RunLoop运行流程。

三、RunLoop在哪里开启

我们知道主线程一开启,就会跑一个和主线程对应的RunLoop,那么RunLoop一定是在程序的入口main函数中开启。

int main(int argc, char *argv[]) {
    @autoreleaspool {
        return UIApplicationMain(argc, argv, nil ,NSStringFromClass([AppDelegate class]));
    }
}

进入UIApplication

UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString *__nullable principalClassName, NSString *__nullable delegateClassName);

我们发现它返回的是一个int,那么我们对main函数做了一些修改

int main(int argc, char * argc[]) {
    @autoreleasepool {
        NSLog(@"开始");
        int re = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        NSLog(@"结束");
        return re;
    }
}

运行程序,我们发现只会打印“开始”,并不会打印结束,说明UIApplicationMain函数中,开启了一个和主程序相关的RunLoop,导致UIApplicationMain不会返回,一直在运行中,也就保证了程序的持续运行。

我们看下RunLoop的源码

// 用Default Model启动
void CFRunLoopRun(void) { /* DOES CALLOUT */
    int32_t result;
    do {
        result = CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);
        CHECK_FOR_FORK();
    } while (kCFRunLoopRunStoped != result && kCFRunLoopRunFinished != result);
}

我们发现RunLoop确实do while 通过判断result来实现的。因此,我们可以把RunLoop看成是一个死循环。如果没有RunLoop,UIApplicationMain函数执行完毕之后将直接返回,无法支持程序的持续运行。

四、RunLoop对象

两个框架支持RunLoop:

  1. Foundation框架的NSRunLoop对象(基于CFRunLoopRef封装)
  2. CoreFoundation框架的CFRunLoopRef(重点学习这一个)

获得Runloop对象

// Foundation
[NSRunLoop currentRunLoop];
[NSRunLoop mainRunLoop];

// Core Foundation
CFRunLoopCurrent();
CFRunLoopGetMain();

RunLoop和线程的关系

  1. 每线程都有唯一一个与之对应的RunLoop对象。
  2. 主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建。
  3. RunLoop在第一次获取时创建,在线程结束时销毁。

1. 主线程相关联的RunLoop创建

CFRunLoopRef源码

// 创建字典
CFMutableDictionaryRef dict = CFDictionaryCreatMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
// 创建主线程,根据传入的主线程创建主线程对应的RunLoop
CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np());
// 保存主线程 将主线程的 -key 和RunLoop-value保存到字典中
CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop);

2. 创建与子线程相关联的RunLoop

CFRunLoopRef源码

    // 从字典中获取子线程的runloop
    CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
    __CFUnlock(&loopsLock);
    if (!loop) {
        // 如果子线程的runloop不存在,那么就为该线程创建一个对应的runloop
    CFRunLoopRef newLoop = __CFRunLoopCreate(t);
        __CFLock(&loopsLock);
    loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
        // 把当前子线程和对应的runloop保存到字典中
    if (!loop) {
        CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
        loop = newLoop;
    }
        // don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it
        __CFUnlock(&loopsLock);
    CFRelease(newLoop);
    }

从上面的代码可以看出,线程和RunLoop之间是一一对应的,其关系是保存在一个字典中,所以我们创建子线程RunLoop时,需要在子子线程中获取当前线程的RunLoop对象即可[NSRunLoop currentRunLoop];如果不获取,子线程就不会创建与之相关联的RunLoop,并且只能在一个线程的内部获取其RunLoop

[NSRunLoop currentRunLoop];方法调用时,会去先查看一下字典里有没有存子线程相对应的RunLoop,有则直接返回,否则就创建一个存在字典中


原文:
https://www.jianshu.com/p/b9426458fcf6

相关文章

  • iOS知识点(10)RunLoop

    深入理解RunLoop iOS---实例化讲解RunLoop iOS runloop iOS-RunLoop充满灵...

  • 深入浅出Runloop

    书上得来终觉浅、绝知此事要躬行。本文参考来源:http://mrpeak.cn/blog/ios-runloop/...

  • iOS-RunLoop,为手机省电,节省CPU资源,程序离不开的

    转载:iOS-RunLoop,为手机省电,节省CPU资源,程序离不开的机制 RunLoop是什么?基本操作是什么?...

  • iOS-RunLoop

    什么是RunLoop?从字面意思看:运行循环、跑圈其实它内部就是do-while循环,在这个循环内部不断地处理各种...

  • ios-RunLoop

    - 什么是RunLoop? 从字面理解,循环跑。你也可以叫它事件循环,消息循环。本质是一个do{}while(0)...

  • iOS-RunLoop

    现在对iOS开发者要求越来越高,RunLoop其实在开发中很少会用到但是也需要我们去了解。 RunLoop简单介绍...

  • iOS-RunLoop

    本文主要内容: 概念 数据结构 事件循环的实现机制 RunLoop与NSTimer RunLoop与线程 源码 一...

  • iOS-RunLoop

    做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是...

  • iOS-RunLoop

    2016年8月2日 RunLoop 有两种类型的RunLoop,一种是Foundation框架的 NSRunLoo...

  • iOS-Runloop

    一、概述 Runloop,运行循环,在程序启动后,一直循环的做一些事情。Runloop程序会一直运行并时刻等待用户...

网友评论

      本文标题:iOS-RunLoop

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