首先是文档对CFRunLoop部分的一个概述,可以帮助我们简单的了解一下CFRunLoop的主要的特性:
Overview
A CFRunLoop object monitors sources of input to a task and dispatches control when they become ready for processing. Examples of input sources might include user input devices, network connections, periodic or time-delayed events, and asynchronous callbacks.
Three types of objects can be monitored by a run loop: sources (CFRunLoopSource Reference), timers (CFRunLoopTimer Reference), and observers (CFRunLoopObserver Reference). To receive callbacks when these objects need processing, you must first place these objects into a run loop withCFRunLoopAddSource,CFRunLoopAddTimer, orCFRunLoopAddObserver. You can later remove an object from the run loop (or invalidate it) to stop receiving its callback.
Each source, timer, and observer added to a run loop must be associated with one or more run loop modes. Modes determine what events are processed by the run loop during a given iteration. Each time the run loop executes, it does so in a specific mode. While in that mode, the run loop processes only the events associated with sources, timers, and observers associated with that mode. You assign most sources to the default run loop mode (designated by thekCFRunLoopDefaultMode constant), which is used to process events when the application (or thread) is idle. However, the system defines other modes and may execute the run loop in those other modes to limit which sources, timers, and observers are processed. Because run-loop modes are simply specified as strings, you can also define your own custom modes to limit the processing of events
Core Foundation defines a special pseudo-mode, called the common modes, that allow you to associate more than one mode with a given source, timer, or observer. To specify the common modes, use thekCFRunLoopCommonModes constant for the mode when configuring the object. Each run loop has its own independent set of common modes and the default mode (kCFRunLoopDefaultMode) is always a member of the set. To add a mode to the set of common modes, use theCFRunLoopAddCommonMode function.
There is exactly one run loop per thread. You neither create nor destroy a thread’s run loop. Core Foundation automatically creates it for you as needed. You obtain the current thread’s run loop withCFRunLoopGetCurrent. Call CFRunLoopRun to run the current thread’s run loop in the default mode until the run loop is stopped withCFRunLoopStop. You can also callCFRunLoopRunInMode to run the current thread’s run loop in a specified mode for a set period of time (or until the run loop is stopped). A run loop can only run if the requested mode has at least one source or timer to monitor.
Run loops can be run recursively. You can call CFRunLoopRun orCFRunLoopRunInMode from within any run loop callout and create nested run loop activations on the current thread’s call stack. You are not restricted in which modes you can run from within a callout. You can create another run loop activation running in any available run loop mode, including any modes already running higher in the call stack.
Cocoa applications build upon CFRunLoop to implement their own higher-level event loop. When writing an application, you can add your sources, timers, and observers to their run loop objects and modes. Your objects will then get monitored as part of the regular application event loop. Use the getCFRunLoop method of NSRunLoop to obtain the correspondingCFRunLoopRef type. In Carbon applications, use theGetCFRunLoopFromEventLoop function.
For more information about how run loops behave, see “Run Loops” in Threading Programming Guide.
大致的翻译:CFRunLoop对象监控任务(task)的输入源,并在它们为处理做好准备的时候调度控制。输入源样例可能包括用户输入设备、网络链接、定期或时间延迟事件,还有异步回调。
有3类对象可以被run loop监控:sources、timers、observers。
当这些对象需要处理的时候,为了接收回调,首先必须通过 CFRunLoopAddSource
,CFRunLoopAddTimer
,or CFRunLoopAddObserver
把这些对象放入run loop。 要停止接收它的回调,你也可以稍候通过CFRunLoopRemoveSource从runloop中移除某个对象。
run loop有不同的运行模式,每种模式都有其自身的对象集,runloop监控,同时在该模式下运行。
Core Foundation还定义了一个特殊的伪模式kCFRunLoopCommonModes来持有应当被“common”模式集共享的对象。 kCFRunLoopCommonModes
每个线程恰好有一个run loop,既不可以创建,也不能销毁线程的run loop。,Core Foundation根据需要为你创建。通过CFRunLoopGetMain CFRunLoopRun
run loop可以递归运行,你可以在任何run loop标注内部调用CFRunLoopRun
CFRunLoopRunInMode,还可以创建嵌套run loop,并在当前线程调用栈激活,在标注内并没有限制在那种模式可以运行。
你可以创建另一个runloop,激活运行在任何可行的run loop模式,包括任何已经运行在调用堆栈中的更高的模式。
getCFRunLoop
GetCFRunLoopFromEventLoo p
例子1,在NSThread创建Run Loop:
IPhone多线程编程提议用NSOperation和NSOperationQueue,这个接口苹果已经封装的很具有自动化的效果,对开发者来说,更简单易用。
但是有些情况下,我们还是在运行一些长线任务或者复杂任务的时候,还是需要用到NSThread,这就需要为NSThread创建一个run loop.
//创建一个新的线程,其中object:nil部分可以作为selector的参数传递,在这里没有参数,设为nil
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(playerThread: ) object:nil];
//开启线程,如果是利用NSOperation,只需要加入到NSOperationQueue里面去就好了,queue自己会在合适的时机执行线程,而不需要程序员自己去控制。
[thread start];
- (void) playerThread:id)unused
{
currentLoop = CFRunLoopGetCurrent();//子线程的runloop引用
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];//为子线程创建自动释放池
//run loop
[self initPlayer];
//CFRunLoopRun,Runs the current thread’s CFRunLoop object in its default mode indefinitely.
CFRunLoopRun();
//run loop,这里就会停住了。
[pool release];
}
// 实现一个timer,用于检查子线程的工作状态,并在合适的时候做任务切换。或者是合适的时候停掉
// 自己的run loop
-(void) initPlayer
{
// 在这里你可以初始化一个工作类,比如声音或者视频播放
NSTimer *stateChange = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self
selector:@selector(checkState:) userInfo:nil repeats:YES];
}
-(void) checkState:(NSTimer*) timer
{
if(需要退出自定义的线程了)
{
//释放子线程里面的资源
//释放资源的代码....
/*结束子线程任务 CFRunLoopStop,This function forces rl to stop running and
return control to the function that called CFRunLoopRun or CFRunLoopRunInMode
for the current run loop activation. If the run loop is nested with a callout
from one activation starting another activation running, only the innermost
activation is exited.*/
CFRunLoopStop(currentLoop);
}
}
例子2,用Run Loop控制动画的过程:
#import "UIView-ModalAnimationHelper.h"
@interface UIViewDelegate : NSObject
{
CFRunLoopRef currentLoop;
}
@end
@implementation UIViewDelegate
-(id) initWithRunLoop: (CFRunLoopRef)runLoop
{
if (self = [super init]) currentLoop = runLoop;
return self;
}
-(void) animationFinished: (id) sender
{
CFRunLoopStop(currentLoop);
}
@end
@implementation UIView (ModalAnimationHelper)
+ (void) commitModalAnimations
{
CFRunLoopRef currentLoop = CFRunLoopGetCurrent();
UIViewDelegate *uivdelegate = [[UIViewDelegate alloc] initWithRunLoop:currentLoop];
[UIView setAnimationDelegate:uivdelegate];
[UIView setAnimationDidStopSelector:@selector(animationFinished:)];
[UIView commitAnimations];
CFRunLoopRun();
[uivdelegate release];
}
@end
//应用
[UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.4f];
......
[UIView commitModalAnimations];