美文网首页
RunLoop总结

RunLoop总结

作者: 细雨菲菲v | 来源:发表于2018-07-19 17:25 被阅读7次

1.什么是runloop?

RunLoop是通过内部维护的事件循环来对事件/消息进行管理的一个对象。

事件循环

  • 没有消息需要处理时,休眠以避免资源占用


    截图1.png
  • 有消息处理时,立刻被唤醒


    截图2.png

main函数是为什么可以一直保证运行状态,而不退出 ?
在main函数当中,所调用的UIApplicationMain()内部会启动主线程的runloop,而runloop又是对事件循环的一种维护机制,可以做到在有事做的时候做事,没有事情做的时候,会通过从用户态到内核态的切换,从而避免资源的占用,让当前线程处于一种休眠状态。

2.数据结构

NSRunLoop是CFRunLoop的封装,提供了面向对象的API.

  • CFRunLoop
  • CGRunLoopMode
  • Source/Timer/Observer

CFRunLoop

截图3.png
CFRunLoopMode
截图4.png
CFRunLoopSource
  • source0
    需要手动唤醒线程
  • source1
    具备唤醒线程的能力

CFRunLoopTimer
基于事件的定时器

CFRunLoopObserver
观测时间点

  • kCFRunLoopEntry
  • kCFRunLoopBeforeTimers
  • kCFRunLoopBeforeSources
  • kCFRunLoopBeforeWaiting
  • kCFRunLoopAfterWaiting
  • kCFRunLoopExit

各个数据结构之间的关系

截图5.png
RunLoop的Mode
截图6.png
CommonMode的特殊性

NSRunLoopCommonModes

  • CommonMode不是实际存在的一种Mode。
  • 是同步Source/Timer/Observer到多个Mode中的一种技术解决方案

3.事件循环的实现机制

void CFRunLoopRun()

截图7.png
截图8.png

4.NSRunLoop与NSTimer

滑动TableView的时候我们的定时器还会生效吗?

截图9.png
解决方案
void CFRunLoopAddTimer(runLoop, timer,commonMode)

5.RunLoop与多线程

线程和RunLoop一一对应的。
自己创建的线程默认是没有RunLoop的

(1)怎样实现一个常驻线程?

a.为当前线程开启一个RunLoop;
[NSRunLoop currentRunLoop]或者CFRunLoopGetCurrent()
b.向该RunLoop中添加一个Port/Source等维护RunLoop的事件循环;
c.启动该RunLoop。

#import "MCObject.h"
@implementation MCObject
static NSThread *thread = nil;
// 标记是否要继续事件循环
static BOOL runAlways = YES;
+ (NSThread *)threadForDispatch{
    if (thread == nil) {
        @synchronized(self){
            if (thread == nil) {
                //线程的创建
                thread = [[NSThread alloc] initWithTarget:self selector:@selector(runRequest) object:nil];
                [thread setName:@"com.imooc.thread"];
                //启动
                [thread start];
            }
        }
    }
    return thread;
}
- (void)runRequest{
    //创建一个source
    CFRunLoopSourceContext context = {0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
    CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
    //创建RunLoop,同时向RunLoop的DefaultMode下面添加Source
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    //如果可以运行
    while (runAlways) {
        @autoreleasepool {
          //令当初RunLoop运行在DefaultMode下面
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10,true);
        }
    }
    //某一时机 静态变量 runAlways = NO时,可以保证跳出RunLoop,线程退出
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}
@end

6.问题总结

(1)什么是RunLoop,它是怎样做到有事做事,没事休息的?

RunLoop实际是一个事件循环,用于处理事件和消息以及对它们进行管理。由于在调用CFRunLoopRun之后会调用系统的mach_msg()函数,同时发生了从用户态向核心态的切换,然后当前线程处于休眠状态,所以可以做到有事做时,做事没事做时休息。

(2)RunLoop与线程是怎样的关系?

a.runloop与线程是一一对应的关系
b.一个线程默认是没有runloop的,需要手动创建。

(3)实现一个常驻线程

我们可以通过三个步骤,第一个步骤呢,创建一个线程对应的runloop,之后向这个runloop中添加source、timer、observer、port等内容,第三步调用CFRunLoop的一个run方法就可以实现一个常驻线程。在具体使用的过程中,需要注意,运行的模式和资源添加的模式必须是同一个,否则应为外部使用了while循环,就导致了一个死循环

(4)怎样保证子线程数据回来更新UI的时候不打断用户的滑动操作?

在用户进行滑动过程中,当前的runloop运行在UITrackingRunLoopMode,我们对网络请求一般放在子线程中进行的,而子线程返回给主线程的数据呢,我们要抛给主线程,用来更新UI,这个时候我们可以通过把子线程抛会给主线程更新UI的逻辑包装起来,给它提交到主线程的default模式下面,这样的话,抛回来的任务,当前用户正在滑动过程中处于UITrackingRunLoopMode模式下,我们分派到defalut的模式下的任务就不会执行,而当我们手停止滑动操作之后,当前线程它的mode切换到了,default模式下,这个时候处理子线程上抛给主线程的任务,对它进行处理,这样就不会打断用户的滑动操作。

相关文章

  • RunLoop

    RunLoop 文章已经很多了,结合各大文章做个总结 什么是 RunLoop RunLoop 人如其名,run 跑...

  • iOS RunLoop 总结以及相关面试题解答

    iOS RunLoop 总结以及相关面试题解答 iOS RunLoop 总结以及相关面试题解答

  • NSRunLoop

    【iOS程序启动与运转】- RunLoop个人小结 RunLoop总结:RunLoop的应用场景(三) 走进Run...

  • iOS开发经验(18)-Runloop

    目录 Runloop RunLoop 与线程 个人理解总结 应用场景 1. 什么是RunLoop 基本作用 保持程...

  • 探寻RunLoop的本质

    iOS底层原理总结 - RunLoop 面试题 讲讲 RunLoop,项目中有用到吗? RunLoop内部实现逻辑...

  • iOS面试点文章链接

    runtime基础方法、用法、消息转发、super: runtime 完整总结 runloop源码、runloop...

  • RunLoop数据结构、RunLoop的实现机制、RunLoop

    推荐阅读:备战2020——iOS全新面试题总结 RunLoop概念 RunLoop的数据结构 RunLoop的Mo...

  • RunLoop

    iOS刨根问底-深入理解RunLoop runloop 和线程有什么关系 iOS 多线程:RunLoop详细总结

  • RunLoop 的相关概念

    此篇为对 RunLoop 的相关概念的总结,主要介绍 RunLoop 的一些概念 RunLoop 简介 RunLo...

  • RunLoop相关

    iOS底层原理总结 - RunLoop解密 Runloop Runloop是一种在当前线程,持续调度各种任务的运行...

网友评论

      本文标题:RunLoop总结

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