runLoop
来源:互联网 发布:帝国cms系统目录 编辑:程序博客网 时间:2024/05/22 13:43
RunLoop
RunLoop就是运行循环,处理app中的各种事件(比如触摸事件,定时器事件,Selector事件)
一个线程对应一个RunLoop,主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建,RunLoop在第一次获取时创建,线程结束时销毁
RunLoop的获得
- Foundation
- [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
- [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
- Core Foundation
- CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
- CFRunLoopGetMain(); // 获得主线程的RunLoop对象
RunLoop相关类
- Core Foundation中关于RunLoop的5个类
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
RunLoop的组成
- Mode
- Timer
- source
- Observer
Mode
Mode代表RunLoop的运行模式。每次RunLoop职能指定一个Mode运行。切换Mode职能退出Loop,再重新指定一个Mode进入。
一个 RunLoop 包含若干个 Mode,每个Mode又包含若干个Source/Timer/Observer
系统默认的5个Mode
NSDefaultRunLoopMode:App的默认Mode,通常主线程是在这个Mode下运行
UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
NSRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode(既执行Default中的事件也执行track中的事件)
Timer
CFRunLoopTimerRef是基于时间的触发器
CFRunLoopTimerRef基本上说的就是NSTimer,它受RunLoop的Mode影响
GCD的定时器不受RunLoop的Mode影响
- (void)timer{ NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES]; // 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作(比如textField的拖动) // [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; // 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作 // [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; // 定时器会跑在标记为common modes的模式下 // 标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];}- (void)timer2{ // 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES]; // 修改模式 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];}- (void)run{ NSLog(@"----run");}
Source
CFRunLoopSourceRef是事件源(输入源)
按照官方文档,Source的分类
- Port-Based Sources (跟其他线程交互,或通过内核发送的消息)
- Custom Input Sources (自动以输入源,几乎不用)
- Cocoa Perform Selector Sources (比如performSelecter等方法)
按照函数调用栈,Source的分类
- Source0:非基于Port的
- Source1:基于Port的,通过内核和其他线程通信,接收、分发系统事件
事件的传入都是先传入Source1。然后再由Source1分发至source0进行处理。所以在函数调用栈中往往只看到Source0。
Obersver
CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变
- 可以监听的时间点
/* Run Loop Observer Activities */typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { kCFRunLoopEntry = (1UL << 0), // 1 kCFRunLoopBeforeTimers = (1UL << 1), // 2 kCFRunLoopBeforeSources = (1UL << 2), // 4 kCFRunLoopBeforeWaiting = (1UL << 5), // 32 kCFRunLoopAfterWaiting = (1UL << 6), // 64 kCFRunLoopExit = (1UL << 7), // 128 kCFRunLoopAllActivities = 0x0FFFFFFFU};
- 添加Observer
- (void)observer{ // 创建observer CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { NSLog(@"----监听到RunLoop状态发生改变---%zd", activity); }); // 添加观察者:监听RunLoop的状态 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode); // 释放Observer //凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release //比如CFRunLoopObserverCreate //release函数:CFRelease(对象); CFRelease(observer);}
RunLoop处理逻辑
- 1:通知观察者run loop已经启动
- 2:通知观察者任何即将要开始的定时器
- 3:通知观察者任何即将启动的source0
- 4:启动任何准备好的source0
- 5:如果接收到source1准备好并处于等待状态,立即启动,并进入步骤9
- 6:通知观察者线程进入休眠
- 7:将线程置于休眠直到任何一下面的事件发生:
- 某一事件到达source1
- 定时器启动
- runloop设置的时间超时
- runloop被显式唤醒
- 8:通知观察者线程将被唤醒
- 9:处理未处理的事件
- 如果用户定义的定时器启动,处理定时器事件并重启runloop,进入步骤2
- 如果输入源启动,传递相应的消息
- 如果runloop被显示唤醒而且时间还未超时,重启runloop,进入步骤2
- 10:通知观察者runloop结束
0 0
- runloop
- runloop
- runloop
- RunLoop
- RUNLOOP
- RunLoop
- RunLoop
- RunLoop
- runloop
- RunLoop
- runloop
- runloop
- runloop
- runloop
- Runloop
- RunLoop
- RunLoop
- runloop
- Android集成百度地图SDK
- JS中的phototype浅谈
- 文本框相关样式设置
- bzoj4238: 电压
- Android 自定义 dialog
- runLoop
- javascript中new Date()的浏览器兼容性问题解决方案
- 使用curl指令測試REST服務
- C#读取xml文件
- android权限
- 针对IE的条件注释
- http://www.cnblogs.com/hnrainll/archive/2011/12/29/2305582.html
- JSONP跨域原理
- 来段代码提提神-Java实现SocketServer和client链接