iOS runloop详解
写这篇文章开始之前,我都不知道runloop是什么东西,如果从字面的意思翻译应该是一直循环的跑,怀疑可能和死锁有关系,可是死锁具体是怎么回事,我只是记得有这个说法,也发现了一个自己不懂的知识。
初识runloop
我在网上看了一下@sunnnyxx 关于runloop的视频.了解了一下runloop相关知识,也去网络上看各种关于runloop的讲述。
我们一般程序就是执行一个线程,是一条直线,有起点终点,而runloop就是一直在线程上面画圆圈,一直在跑圈,除非切断否则一直在运行。网上说的比喻很好,直线就像昙花一现一样,圆就像os,一直运行直到你关机为止。
在我们学习iOS生命周期里面都会存在销毁的过程,但是屏幕好像一直能接收各种指令,感觉很像runloop的功效,好像这些是和顶层UIKit无关,iOS架构最底层是Core OS,我分析应该是苹果封装好了,只是我们看不到源码而已。
为什么要使用runloop
回到开始的疑问,为什么要使用runloop,一般情况下我们是没必要去启动线程的runloop,除非需要在一个单独的线程长久的检测某个事件,就像视频里面提到的类似微信的语音功能,见一个runloop专门负责监听说话的线程。看需求而定了。
CFRunLoopSource
Source是RunLoop的数据源抽象类,类似iOS中protocol
RunLoop定义两个Version的Source
Source0:处理app内部事件,App自己负责管理(触发),如UIEvent,CFSocket
Source1:由RunLoop和内核管理,Mach port驱动如CFMach、CFMessage
CFRunLoopObserver
向内部报告runloop当前状态的更改CAAnimation
RunLoopObserver 与 Autorelease Pool
UIKit通过RunLoopObserver在RunLoop两次Sleep间对AutoreleasePool进行pop和push,将这次Loop中产生的Autorelease对象释放。(好像swift中没有关于释放的问题)
CFRunLoopMode
runloop在同一时段只能且必须在一种特定Mode下Run更换Mode 时,需要暂停当前的loop,然后重启新的loop
NSDefalutRunLoopMode 默认状态,空闲状态
UITrackingRunLoopMode 滑动ScrollView
UIInitializationRunLoopMode 私有,App启动时
NSRunLoopCommonModes 默认包括上面第一和第二
UITrackingRunLoopMode 与 NSTimer
默认情况下 NSTimer 被加入NSDefalutRunLoopMode,如果想NSTimer受到组件或者动画影响添加到NSRunLoopCommonModes(oc代码如下:)
[[NSRunLoop currentRunLoop]addTimer:timer...forMode:NSRunLoopCommonModes];
swift版代码:
NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
RunLoopMode切换
NSDefaultRunLoopMode->UITrackingRunLoopMode->NSDefalutRunLoopMode
RunLoop的挂起与唤醒
制定用于唤醒的 mach_port端口
调用mach_msg监听唤醒端口,被唤醒前,系统内核将这个线程挂起,停留在mach_msg_trap
由另外一个线程(或另一个进程中的某个线程)向内核发送这个端口的msg后,trap状态被唤醒,RunLoop继续开始干活
AFNetWorking 中创建RunLoop
创建一个常驻服务线程的很好方法
var loop = NSRunLoop.currentRunLoop()
loop.addPort(NSMachPort(), forMode: NSDefaultRunLoopMode)
loop.run()
一个TableView延迟加载图片的新思路
让Crash的App回光返照 只针对Signal Crash