1.什么是runloop 。用来干嘛的
正常情况下,我们让一个线程执行一个任务,执行完成后线程就退出了。但是实际中,我们可能需要线程随时处理事件并不因为一个任务执行结束而退出。想让这个线程在有任务时处理任务,没任务时休息,避免资源占用,在消息到来时被唤醒。那么Runloop就是做这件事儿的。它实际上就是一个对象,管理着需要处理的任务。前边说一个线程执行一个任务,通过前边说的runloop的作用,我们知道,runloop是与线程一一对应的。也就是说每一个线程都有一个runloop,但是这里需要注意的是,runloop如果你不通过getCurrentLoop去获取,他其实并没有生成,因为并不是你在所有线程里做操作,都是需要有这样一个管家的,当你需要时,调用getCurrentLoop,里边会自动判断是否存在对应线程的runloop,如果不存在就会自动创建一个。并且我们只能在线程内部去获取这个runloop,主线程的runloop除外。
当有持续的异步任务需求时,我们需要创建一个独立的生命周期可控的线程。Runloop就是控制线程生命周期并接收事件进行处理的机制。
Foundation: NSRunLoop
Core Foundation: CFRunLoop 核心部分,代码开源,C 语言编写,跨平台
2.runloop的原理
就是一个do while循环
3.runloop的mode有哪些
1). kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的。
2). UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响。
3). UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用。
4). GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到。
5). kCFRunLoopCommonModes: 这是一个占位的 Mode,没有实际作用。
4.什么是source0 什么是source1
他们是CFRunLoopSourceRef的两种类型,也就是事件产生的两种类型。
source0只包含了一个回调,其实就是一个函数指针,当这个函数指针被调用的时候,就发出了一个source0类型的事件元,所以它并不能主动触发事件,使用时,你需要先调用 CFRunLoopSourceSignal(source),将这个 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp(runloop) 来唤醒 RunLoop,让其处理这个事件。
source1包含了一个mach_port和一个回调,mach_port是一个系统内部的端口,通过这个端口发送消息而产生的事件元就是source1类型,这种source能够主动唤醒runloop所在的线程
source0指的是非基于端口por,说白了也就是处理触摸事件,selector事件,source1指的是基于端口的port:是处理系统的一些事件
6.mode中有哪些东西?
source ,observer和timer
7.每个线程都有runloop么?
每个线程都只能对应一个runloop,但是除了主线程对应的runloop外,其他线程的runloop都需要通过在相应的线程中通过调用currentRunloop方法主动获取,才会生成,而主线程的runloop是启动时系统自己生成的,不需要手动生成,也不要手动生成。否则会如何?可以想想。
8.怎么退出runloop参考文章
设置超时时间,runloop的启动方式有两种一种是默认启动,另外一种是指定mode启动,两种启动方式都调用了CFRunLoopRunSpecific函数,这个函数可以设置一个超时时间。
当然了上述所说都是底层的实现,我们实际调用的时候是调用如下方法的。
- (void)runUntilDate:(NSDate*)limitDate;
指定超时时间,mode是default
- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate*)limitDate;
指定mode 和 超时时间。
第二种方法是直接调用CFRunLoopStop方法结束。比较暴力了。
我们在创建一个runloop的时候,在启动RunLoop之前,必须添加监听的输入源事件source或者定时源事件timer,否则调用[runloop run]会直接返回,而不会进入循环让线程长驻。
那是不是把所有的source和timer都删除了就可以让runloop退出呢?并不是的:
一些系统例行程序给 runloop 添加一些 input source 来处理必要的事件。你的代码可能无法看出这些 input source,你可能不能移除这些用来防止 runloop 退出的 source。
这一条是写于runloop官方文档中的,但是如果你真的能过全部移除,那也确实可以退出runloop
第三种 优雅的退出runloop
然后在调用CFRunLoopStop的地方将_shouldStopRun = YES;
网友评论