RunLoop
一、什么是RunLoop
- 从字面意思理解:运行循环、跑圈。
- 基本作用:
- 保持程序(应用)的持续运行。
- 处理程序(APP)中的各种事件(比如:触摸事件、定时事件、Selector事件等)
- 节省CPU资源,提高程序的性能:调度CPU,该做事时做事,该休息时休息。
- 每个程序中的RunLoop是在Main函数中创建的,实际上是在以下代码中创建的
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
二、RunLoop 对象
- iOS中有两套API来访问和使用RunLoop:Foundation(OC,面向对象:NSRunLoop类)、Core Foundation(C,面向对象:CFRunLoop类)
- NSRunLoop和CFRunLoop都是代表着RunLoop对象,但是NSRunLoop是基于CFRunLoop的一层OC包装,所以要了解RunLoop的内部结构,需要多研究CFRunLoop层面的API(Core Foundation层面)。
三、RunLoop与线程
- 每条线程都有唯一的一个与之对应的RunLoop对象。
- 主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建。
- RunLoop在第一次获取时创建,在线程结束时销毁。
四、获取RunLoop对象
- Foundation框架
[NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
[NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象 - Core Foundation框架
CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
CFRunLoopGetMain(); // 获得主线程的RunLoop对象
五、RunLoop 相关类
- CFRunLoopRef:RunLoop的对象类。
- CFRunLoopModelRef:代表RunLoop的运行模式。
系统默认注册了5个Model:
kCFRunLoopDefaultMode: APP的默认Model,通常主线程是在这个Model下运行。
UITrackingRunLoopMode: 界面跟踪Model,用于Scrollview追踪触摸滑动,保证界面滑动时不受其他Model影响。
UIInitializationRunLoopModel: 刚启动APP时进入的第一个Model,启动完成后就不再使用。
GSEventReceiveRunLoopModel: 接受系统事件的内部Model,通常用不到。
kCFRunLoopCommonModes: 这是一个占位用的Model,不是一种真正的Model。话句话说,是一种标记,这种标记存在以下两种模式中:kCFRunLoopDefaultMode、UITrackingRunLoopMode。- 一个RunLoop包含若干个Model,每个Model又包含若干个Source、Timer、Observer。
- 每次RunLoop启动时,只能指定其中一个Model,这个Model被称作CurrentModel。
- 如果需要切换Model,只能退出Loop,再重新指定一个Model进入。
- CFRunLoopSourceRef:是事件源(输入源)。
按照官方文档,Source的分类:
① Port-Based Source (系统内核中的事件)。
② Custom Input Source (自定义事件)。
③ Cocoa Perform Selector Source。 按照函数调用栈,Source的分类:
① Source0:非基于Port的。
② Source1:基于Port的,通过内核和其他线程通信,接收、分发系统事件。 - CFRunLoopTimerRef:是基于时间的触发器,基本上说的就是NSTimer,它是受Model影响的。
- CFRunLoopObserverRef:是观察者,能够监听RunLoop的状态改变。
可以监听的时间点有以下几个:
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << ), // 即将进入Loop
kCFRunLoopBeforeTimers = (1UL << ), // 即将处理 Timer
kCFRunLoopBeforeSources = (1UL << ), // 即将处理 Source
kCFRunLoopBeforeWaiting = (1UL << ), // 即将进入休眠
kCFRunLoopAfterWaiting = (1UL << ), // 刚从休眠中唤醒
kCFRunLoopExit = (1UL << ), // 即将推出Loop
kCFRunLoopAllActivities = 0x0FFFFFFFU // RunLoop的全部活动
};
/******************************举例如下****************************************/
// 添加observer
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAlloca torGetDefault(), kCFRunLoopAllActivities, YES, , ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"---监听到RunLoop的活动状态------%lu", activity);
});
// 添加观察者:监听RunLoop的状态
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode); - RunLoop 的运行逻辑理解

六、RunLoop 应用
- NSTimer 的使用。
- performSelector 的使用。
- ImageView的显示。
- 常驻子线程。自动释放池(自动释放在进入RunLoop时创建,在RunLoop休眠前(kCFRunLoopBeforeWaiting)释放)。
七、总结
- RunLoop浅层了说就是运行循环;深层次的说它内部就是一个do-while循环,在这个循环中不断的处理各种任务(比如:source、timer、observer)。
- 一个线程对于一个RunLoop,主线程的RunLoop默认是自动开启的,子线程的RunLoop需要手动去启动(调用RunLoop的run方法)。
- RunLoop只能选择一种Model启动,如果当前Model中没有Source(source0、source1)、Timer,那么就会直接退出RunLoop(注意:添加Observer进去无效)。
RunLoop的更多相关文章
- RunLoop 总结:RunLoop的应用场景(一)
参考资料 好的书籍都是值得反复看的,那好的文章,好的资料也值得我们反复看.我们在不同的阶段来相同的文章或资料或书籍都能有不同的收获,那它就是好文章,好书籍,好资料.关于iOS 中的RunLoop资料非 ...
- 我的runloop学习笔记
前言:公司项目终于忙的差不多了,最近比较闲,想起叶大说过的iOS面试三把刀,GCD.runtime.runloop,runtime之前已经总结过了,GCD在另一篇博客里也做了一些小总结,今天准备把ru ...
- [tableView reloadData] 和 runloop
需要[tableView reloadData]后需要立即获取tableview的cell.高度,或者需要滚动tableview,那么,直接在reloadData后执行代码是会有问题的. 断点调试感觉 ...
- RunLoop 总结:RunLoop的应用场景(二)
上一篇讲了使用RunLoop保证子线程的长时间存活,而不是执行完任务后就立刻销毁的应用场景.这一篇就讲述一下RunLoop如何保证NSTimer在视图滑动时,依然能正常运转. 参考资料 好的书籍都是值 ...
- iOS多线程-RunLoop简介
什么是RunLoop? 从字面上来看是运行循环的意思. 内部就是一个do{}while循环,在这个循环里内部不断的处理各种任务(比如:source/timer/Observer) RunLoop的存在 ...
- RunLoop(基本操作)
基本概念 -(void)runTimerInThread { //NSAutoreleasePool,没的用 [NSTimer scheduledTimerWithTimeInterval:1.0 t ...
- iOS RunLoop简介
一.什么是RunLoop? RunLoop是运行循环,每个Cocoa应用程序都由一个处于阻塞状态的do/while循环驱动,当有事件发生时,就把事件分派给合适的监听器,如此反复直到循环停止.处理分派的 ...
- 深入理解RunLoop
网上看的一篇文章,写的真好,我得多看几次好好理解理解 膜拜大神,转载至此便于学习查看. 此处标明原文链接:http://blog.ibireme.com/2015/05/18/runloop/ ...
- RunTime&RunLoop初见
什么是runtime 1> runtime是一套底层的c语言API(包括很多强大实用的c语言类型,c语言函数); 2>实际上,平时我们编写的oc代码,底层都是基于runtime实现的 也就 ...
随机推荐
- js实现复选框全选
HTML代码如下: <div> <label><input type="checkbox" name="aAll">全选&l ...
- php 封装 知识点
类由众多对象抽象出来的对象由类实例化出来的 成员变量成员方法成员属性 访问修饰符public 公有的protected 受保护的private 私有的 构造函数1.写法特殊2.执行时间特殊 面向对象的 ...
- 关于for循环------swift3.0
在程序开发当中,for循环使用的频率无疑是最高的.常用的swift循环是递增式遍历.当然各种循环,swift都能办到.但其大多采用关键字形式实现,大部分开发者更喜欢直接使用C式循环代码.在swift3 ...
- Android语录
1. application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期.因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象.因此在 ...
- mac版本cornerstone的无限期破解方法【转】
CornerStone是个人非常喜欢的mac上的一款SVN客户端工具,官方提供了14天的免费试用(trail)版本.我们可以在此基础上提供无限期试用版本. 方法一:如果你从来没有安装过这个trail版 ...
- jsf组件对应表
组件 标签 说明 UIForm form 表示 HTML表单元素 UIInput InputText 单行文本输入控件 inputTextarea 多行文本输入控件 InputSecret 密 ...
- 移动适配请使用比rem等更好的布局方案
移动端大行其道,rem/em.百分比.响应式方案更是层出不穷,看见周围的伙伴们都在对使用rem和百分比情有独钟,可我却偏不爱,之所以出现如此多的方法,其目的只有一个屏幕适配. 屏幕适配顾名思义 ...
- windows 物理内存获取
由于我一般使用的虚拟内存, 有时我们需要获取到物理内存中的数据(也就是内存条中的真实数据), 按理说是很简单,打开物理内存,读取就可以了.但似乎没这么简单: #include "window ...
- 工作中常用的awk命令
http://man.linuxde.net/awk 1.为一列id加逗号 awk 'BEGIN {ORS=","}{print $1}' test.txt 2.统计一列id中重复 ...
- android 查看当前正在运行的进程
转载至 https://github.com/wenmingvs/AndroidProcess 因为Android5.0以上的权限封锁,无法直接获取正在运行的进程,此文总共介绍6中方法获取, 详细介绍 ...