iOS开发笔记--Run Loops(简洁版)
来源:互联网 发布:点位图软件 brd 编辑:程序博客网 时间:2024/04/30 16:28
2012-09-17 11:29 451人阅读 评论(1)收藏 举报
分类:
iOS开发笔记(2)
版权声明:本文为博主原创文章,未经博主允许不得转载。
一、概念
Run loops 是与线程相关的基础构造部分。
一个 run loop就是一个事件处理循环,调配任务和处理输入事件。
run loop的目标就是,有任务的时候保持忙碌,没有任务时休眠。
Cocoa和Core Foundation都提供run loop对象帮助我们配置和管理run loop。
应用不需要显示的创建run loop对象;每个线程,包括主线程都有与之相关的run loop对象。
主线程在程序启动后,会自行创建run loop对象,并运行;只有次线程需要显示的创建run loop对象,并运行。
1.事件来源
run loop有两种事件来源:输入源和定时源。
输入源传递异步消息,消息通常来自其他线程或者不同应用。
定时源传递同步消息,在安排的时间或重复的时间间隔发生。
两种源都使用应用特定的处理路径处理事件。
1)输入源
当你创建输入源后,需要把它分配给一种run loop模式
run loop模式影响在给定时刻哪种输入源会被监控。
输入源的种类
基于端口的源,可定制输入源,cocoa执行函数输入源。
基于端口的源 监控应用相关的端口。
可定制输入源 监控定制的事件来源。
cocoa执行函数输入源 cocoa定义了一个定制的输入源,允许你在任何线程执行函数选择器
2)定时源
2.run loop模式
run loop模式是一个集合,这个集合包括需要监控的输入源和定时源以及需要通知的run loop观察者。
每当你运行run loop时,要给它配一种模式。只有与这种模式相关的事件来源会被监控,并允许发送消息;只有与这种模式相关的runloop观察者会被通知。其他模式相关的事件来源会只有在其模式配给run loop时,才会起作用,否则暂停。
3.run loop观察者
可以创建以下事件相关的观察者
run loop入口
run loop将要处理定时源时
run loop将要处理输入源时
run loop将要休眠时
run loop已被唤醒, 且在它处理唤醒它的事件之前
run loop终止
二、何时使用run loop
只有创建次线程时,才需要显示地运行run loop。
没有必要在所有的情况下启动线程的run loop。例如,用线程执行某个长时间运行并且已经约定好的任务,就应该避免启动runloop。
你需要频繁或者更多地与线程交互,就需要使用run loop。
例如,在以下情况需要启动run loop:
使用端口源或者可定制的输入源与其他线程通信
使用定时器
在cocoa应用中使用 类似performSelector的方法
使用线程执行周期性任务
三、使用run loop对象
run loop对象提供主要的接口,向run loop添加输入源,定时器,观察者以及运行run loop。
每个线程都有一个关联的,单独的run loop对象。
在cocoa中,这个关联对象是NSRunLoop对象;在Carbon或BSD应用中,是CFRunLoopRef类型的指针。
1.获取run loop对象
1)
NSRunLoop*runLoop = [NSRunLoop currentRunLoop];
CFRunLoopRefrunLoopRef = [runLoop getCFRunLoop];
2)
CFRunLoopRefrunLoopRef = CFRunLoopGetCurrent();
2.配置run loop
在次线程上运行run loop之前,必须至少添加一个输入源或者定时器。
如果run loop没有任何来源监控,当你试着运行它时就会立刻退出。
run loop观察者必须用Core Foundation创建。
创建观察者的代码示例
[plain] view plaincopy
- - (void)main
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- //get runloop object
- NSRunLoop*runLoop = [NSRunLoop currentRunLoop];
- //create arun loop observer and attach it to the run loop
- CFRunLoopObserverContext context = {0,self,NULL,NULL,NULL};
- CFRunLoopObserverRef runLoopObserver =CFRunLoopObserverCreate(kCFAllocatorDefault,kCFRunLoopBeforeSources, YES, 0,&runLoopObserverCallBack,&context);
- if(runLoopObserver)
- {
- CFRunLoopRefrunLoopRef = [runLoop getCFRunLoop];
- CFRunLoopAddObserver(runLoopRef, runLoopObserver,kCFRunLoopDefaultMode);
- }
- while(!self.isCancelled && [runLooprunMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]]);
- [pool drain];
- }
3.启动run loop
有几种方法启动run loop,包括以下几种:
- 无条件的
- 预设时间
- 特定模式
无条件的进入run loop是最简单的选择,但是不推荐。无条件运行run loop使线程进入固定的循环,你对runloop只有很少的控制。可以添加或移除事件来源,停止run loop的唯一方式是杀死线程。并且也不能在定制的模式下运行。
预设时间是一种更好的选择。runloop运行,知道接收到一个事件或者预设的时间过期。如果是接到事件,就把时间交给处理器处理,然后退出runloop,你可以重新启动run loop来处理下一个事件;如果是分派的时间过期,你可以简单地重启runloop,使用时间去做其他任何事情。
特定模式也是一种好的选择。模式与预设时间并不冲突,可以同时使用。
示例代码
[plain] view plaincopy
- - (void)main
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- //get runloop object
- NSRunLoop*runLoop = [NSRunLoop currentRunLoop];
- //create arun loop observer and attach it to the run loop
- CFRunLoopObserverContext context = {0,self,NULL,NULL,NULL};
- CFRunLoopObserverRef runLoopObserver =CFRunLoopObserverCreate(kCFAllocatorDefault,kCFRunLoopBeforeSources, YES, 0,&runLoopObserverCallBack,&context);
- if(runLoopObserver)
- {
- CFRunLoopRefrunLoopRef = [runLoop getCFRunLoop];
- CFRunLoopAddObserver(runLoopRef, runLoopObserver,kCFRunLoopDefaultMode);
- }
- BOOL done =NO;
- do {
- //start runloop but return after each source is handled
- SInt32result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, YES);
- // If asource explicitly stopped the run loop, or if there are no
- // sources or timers, go ahead and exit.
- if (result== kCFRunLoopRunStopped || result == kCFRunLoopRunStopped)
- {
- done =YES;
- }
- } while(!done);
- // while(!self.isCancelled && [runLooprunMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]]);
- [pool drain];
- }
4.退出run loop
有两种方法:
- 设定一个时限运行run loop
- 停止 run loop
如果可以设置的话,设定时限的方法优先选择。这种方法可以使runloop在退出之前,完成所有正常的操作,包括发送通知给所有观察者。
使用CFRunLoopStop方法退出run loop,效果与设定时限类似。区别是无条件启动run loop时,不可以使用。
5.线程安全与run loop对象
Core Foundation的方法都是线程安全的。可以在任何线程调用。如果在配置过的run loop执行操作,最好是在拥有该runloop的线程中操作。
NSRunLoop是线程不安全的。使用NSRunLoop配置run loop时,最好在该runloop所属的线程中操作,否则结果不可预期或者崩溃。
四、配置run loop源
暂时搁置,有需要再研读。
http://blog.csdn.net/albert_zhao/article/details/7986865
- iOS开发笔记--Run Loops(简洁版)
- iOS开发笔记--Run Loops
- GCD && Run Loops学习笔记
- iOS:多线程编程指南(二)--Run Loops
- Run Loops
- Run Loops
- Run Loops
- Run loops
- Run Loops
- Run Loops
- Run Loops
- Run loops 的具体执行顺序(ios oc)
- Run loops的使用
- Run Loops(翻译)
- 关于Run Loops
- [IOS 开发] run loop
- 运行循环(Run Loops)
- iOS开发之CocoaPods导入第三方简洁版
- 2016 PayPal开发者平台 如何创建Sandbox测试账户
- 【Hadoop】Hadoop2.7.3执行job下来几个bug和解决思路
- MyBatis批量操作和多参数查询
- tjut 3536
- Binary Tree Level Order Traversal
- iOS开发笔记--Run Loops(简洁版)
- Plus One
- jquery遍历的each方法
- 如何抓取 手机apk的 logcat 日志
- 哪些SEO操作方法会被搜索引擎认为是在作弊?
- USACO 2002 Feb CowCycling
- HTML常用标签
- GAN的模型和理论发展
- bfs/dfs的应用--countComponents