iOS Run loop总结

来源:互联网 发布:淘宝首页设计尺寸990 编辑:程序博客网 时间:2024/05/17 22:44

一、简述

1、RunLoop是事件接收和分发机制的一个实现
2、并且它能处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
3、以及节省CPU资源,提高程序性能:(该做事时做事,该休息时休息)
每一个线程对应着一个 RunLoop ,但是线程在创建的时候是没有 RunLoop 的,如果你不去获取它,它会一直没有,当然必须你自己的主动去获取,但是在你线程结束的时候,你所获取的 RunLoop 也跟着销毁了。如果你需要在某个线程对你自己的 RunLoop 执行一些事件的时候,那么你就的在线程未结束之前进行操作,然而在程序中是具有一个主 RunLoop 的,它用来管理程序的生死,具体的话是在 UIApplicationMain 里面执行
@sunnnyxx 在视频介绍了四个作用:(当然对于我这种新手还没有完全搞懂)
- 使程序一直运行接受用户输入
- 决定程序在何时应该处理哪些Event
- 调用解耦(对于编程经验为0的完全没搞懂这个意思,解释为Message Queue)
- 节省CPU时间
//获取的两种方式
1、这种为CFRunLoopRef中的
CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
CFRunLoopGetMain(); // 获得主线程的RunLoop对象
2、这种为NSRunLoop中的
[NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
[NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象

二、相关类

//相关的五个类
一、CFRunLoopRef
- 代表一个RunLoop对象
二、CFRunLoopModeRef
1、代表RunLoop的运行模式
- 一个RunLoop包含若干个Mode,每个Mode又包含若干个Source/Timer/Observer
- 每次RunLoop启动时,只能指定其中一个 Mode,如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入
- 同一时刻只能进行一种模式
2、苹果内部提供了五种模式
1. kCFRunLoopDefaultMode (NSDefaultRunLoopMode)// App的默认Mode,通常主线程是在这个Mode下运行
2. UITrackingRunLoopMode //界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
3. UIInitializationRunLoopMode //在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
4. GSEventReceiveRunLoopMode //接受系统事件的内部 Mode
5. kCFRunLoopCommonModes //这是一个占位用的Mode,默认包含第一和第二个。
3、UITrackingRunLoopMode 与 NSTimer
默认情况下NSTimer被加入NSDefalutRunLoopMode
如果想将NSTimer加到指定mode,调用下面这个方法
[[NSRunLoop currentRunLoop]addTimer:timer forMode:UITrackingRunLoopMode];

三、CFRunLoopSourceRef
1、用来管理所有事件的事件源,包括自定义的事件,以及系统自带的事件。
2、Source有两个版本:Source0 和 Source1
1、Source0—–为用户主动触发的事件
2、Source1—–通过内核和其他线程相互发送消息。
四、CFRunLoopTimerRef
1、基本上说的就是NSTimer
五、CFRunLoopObserverRef
1、用来监听RunLoop的状态改变
2、状态列表
kCFRunLoopEntry = (1UL << 0), // 即将进入Loop
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理 Timer
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
kCFRunLoopAfterWaiting = (1UL << 6), // 刚从休眠中唤醒
kCFRunLoopExit = (1UL << 7), // 即将退出Loop
kCFRunLoopAllActivities = 0x0FFFFFFFU //所有状态
3、RunLoopObserver 与 Autorelease Pool
UIKit通过RunLoopObserver在RunLoop两次Sleep间对AutoreleasePool进行pop和push,将这次Loop中产生的Autorelease对象释放。(好像swift中没有关于释放的问题)

RunLoop的挂起与唤醒

  • 制定用于唤醒的mach_port端口
  • 调用mach_msg监听唤醒端口,被唤醒前,系统内核将这个线程挂起,停留在mach_msg_trap
  • 由另外一个线程(或另一个进程中的某个线程)向内核发送这个端口的msg后,trap状态被唤醒,RunLoop继续开始干活

RunLoop事件队列

每次运行run loop,你线程的run loop对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:

  • 通知观察者run loop已经启动
  • 通知观察者任何即将要开始的定时器
  • 通知观察者任何即将启动的非基于端口的源
  • 启动任何准备好的非基于端口的源
  • 如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。
  • 通知观察者线程进入休眠
  • 将线程置于休眠直到任一下面的事件发生:
    • 某一事件到达基于端口的源
    • 定时器启动
    • Run loop设置的时间已经超时
    • run loop被显式唤醒
  • 通知观察者线程将被唤醒。
  • 处理未处理的事件
    • 如果用户定义的定时器启动,处理定时器事件并重启run loop。进入步骤2
    • 如果输入源启动,传递相应的消息
    • 如果run loop被显式唤醒而且时间还没超时,重启run loop。进入步骤2
  • 通知观察者run loop结束。
1 0
原创粉丝点击