iOS基础·OC高级篇iOSiOS学习

RunLoop学习笔记

2017-02-18  本文已影响255人  箪食豆羹

参考

深入理解RunLoop

深入研究 Runloop 与线程保活

RunLoop分享by孙源

RunLoop的概念

RunLoop是一个机制,让线程能随时处理事件但并不退出。这种机制实现的关键点在于:如何管理事件/消息,如何让线程在没有处理消息时休眠以避免资源占用、在有消息到来时立刻被唤醒。

iOS提供了两个这样的对象:NSRunLoopCFRunLoopRef

Runloop和线程之间的关系

线程和 RunLoop 之间是一一对应的,其关系是保存在一个全局的 Dictionary 里。线程刚创建时并没有RunLoop,如果你不主动获取,那它一直都不会有。RunLoop 的创建是发生在第一次获取时,RunLoop 的销毁是发生在线程结束时。你只能在一个线程的内部获取其 RunLoop(主线程除外)。主线程的RunLoop是一直运行的,RunLoop在执行完任务后会进入休眠,等待下一次启动。

RunLoop的组成

RunLoop的Mode

RunLoop只能运行在一个mode下,如果要换mode,当前的loop也需要停下重启成新的。

例如:ScrollView滚动过程中NSDefaultRunLoopModekCFRunLoopDefaultMode)的mode会切换到UITrackingRunLoopMode来保证ScrollView的流畅滑动,如果我们把一个NSTimer对象以NSDefaultRunLoopModekCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度,解决方案是将timer添加到NSRunLoopCommonModeskCFRunLoopCommonModes)中或者另起线程避免mode切换来解决。

RunLoop内部逻辑

RunLoop 内部的大致逻辑

RunLoop 内部是一个 do-while 循环。当你调用 CFRunLoopRun()时,线程就会一直停留在这个循环里;直到超时或被手动停止,该函数才会返回。

RunLoop的底层实现

RunLoop 的核心是基于 mach port 的

iOS的内核是Mach,在 Mach 中,所有的东西都是通过自己的对象实现的,进程、线程和虚拟内存都被称为"对象"。和其他架构不同, Mach 的对象间不能直接调用,只能通过消息传递的方式实现对象间的通信。"消息"是 Mach 中最基础的概念,消息在两个端口 (port) 之间传递,这就是 MachIPC (进程间通信) 的核心。

为了实现消息的发送和接收,mach_msg() 函数实际上是调用了一个 Mach 陷阱 (trap),即函数mach_msg_trap(),陷阱这个概念在 Mach 中等同于系统调用。当你在用户态调用 mach_msg_trap() 时会触发陷阱机制,切换到内核态;内核态中内核实现的 mach_msg()函数会完成实际的工作。

RunLoop调用这个函数去接收消息,如果没有别人发送 port 消息过来,内核会将线程置于等待状态。例如你在模拟器里跑起一个 iOS 的 App,然后在 App 静止时点击暂停,你会看到主线程调用栈是停留在mach_msg_trap()这个地方。

iOS利用RunLoop实现的功能

RunLoop常见应用

用到的框架

有关RunLoop的问题

上一篇 下一篇

猜你喜欢

热点阅读