Kevin的IOS开发专题

iOS底层原理-Runloop

2018-07-25  本文已影响24人  我是一只攻城狮_ifYou

Runloop

Runloop作用:

程序中Main函数中的UIApplicationMain函数主要作用就是创建了一个主运行循环
主线程几乎所有的事情都是交给了runloop去完成,比如UI界面的刷新,点击事件的处理,performSelector等等,但并非所有的任务都是由runloop完成

Runloop有两种形式:

Runloop与线程的关系:

Runloop与Mode的关系:

Snip20180601_27.png

Runloop只能选择其中一个mode,称之为CurrentMode
如果需要切换mode,只能退出当前mode,重新选择一个Mode进入
不同组的source0,source1,observers,timer能分隔开,互不影响

注:如果mode里没有任何source0等等的事件,则runloop会立马退出
切换mode也是在Runloop内部,不会导致程序退出

常见的2种Mode:

注:kCFRunloopCommonModes默认包括了kCFRunloopDefaultMode和UITrackingRunloopMode
kCFRunloopCommonModes并不是一个真正的模式,只是一个标记,而kCFRunloopDefaultMode和UITrackingRunloopMode的模式是真正意义的模式,timer在设置了kCFRunloopCommonModes标记的模式下都能运行,而kCFRunloopDefaultMode和UITrackingRunloopMode这两个模式都是kCFRunloopCommonModes标记的,

使用NSRunloop方式和CFRunloopRef的方式获取两者,会发现地址不一致,实际是NSRunloop是对CFRunloopRef的一层封装,其本质地址还是CFRunLoopRef的地址

注:(lldb)bt可以获取函数调用栈

Mode中各个成员的含义:

Runloop运行逻辑:

Snip20180604_1.png

Runloop处理事件一般都是调用_CFRUNLOOP_IS_CALLING_OUT_TO_XXXX函数进行事件处理

GCD中当仅在子线程做事情时,是不依赖Runloop的,但当需要回到主线程等线程间操作的时候,需要runloop来执行

线程休眠其实和线程阻塞类似,但和通过代码例如while(1)令线程阻塞是不一样的,使用代码while(1),线程并未休眠,而是不断进行while(1)判断,汇编也并未停止,而线程休眠是可以真正意义上做到令线程不做任何的事情

Runloop休眠的实现原理: 会从用户态切换到内核的内核态,在内核态执行休眠的目的,是可以实现真正意义上的休眠(即没有消息就是休眠,有消息就唤醒,并回到用户态)

Runloop响应用户操作具体流程:先通过source1事件进行捕捉,然后再source0事件进行处理

Runloop在实际开发中的应用:


NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 
                                                 repeats:YES          
                                                 block:^(NSTimer * _Nonnull timer) {
            
        }
        
//带有schedule的是会将定时器直接添加到默认的模式

NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            
        }]
//该方法不会添加到默认模式去,只会单纯创建一个timer
//后续需要手动调用runloop的addtimer方法才能令定时器工作

Runloop的run方法是一个无线的循环,故外部停止runloop只是停止其中一次循环,故是无法停止Runloop的,run方法用于开启一个永不销毁的线程

使用runMode方法在唤醒后,做完对应事情,runloop就会退出

performSelector方法的waitUntilDone设置为YES,代表该语句执行完后才会执行后面的语句,设置为NO,则后面语句与该语句是一起执行的

GCD只负责创建线程,不负责线程保活

一个问题:

Q:保住线程的命为什么要用Runloop,用强指针不就好了?
A:准确的说,使用Runloop是为了让线程保持激活状态,线程的任务一旦执行完毕,生命周期就结束,无法再使用

上一篇 下一篇

猜你喜欢

热点阅读