RunLoop

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RunLoop相关的知识,希望对你有一定的参考价值。

首先是文档对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 thekCFRunLoopCommonModesconstant 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监控,同时在该模式下运行。 CoreFoundation定义了一种默认模式kCFRunLoopDefaultMode来持有对象,在应用或线程闲置的时候这些对象应该被监控。当一个对象被添加到不认识的模式时,额外模式自动创建。每个runloop有它自己独立的模式集。

Core Foundation还定义了一个特殊的伪模式kCFRunLoopCommonModes来持有应当被“common”模式集共享的对象。 通过调用CFRunLoopAddCommonMode来添加一个模式到“common”模式集。 默认模式kCFRunLoopDefaultMode 总是common模式集中的一个成员。kCFRunLoopCommonModes 常数决不会传给CFRunLoopRunInMode 。每个runloop有它自己独立的common模式集。

每个线程恰好有一个run loop,既不可以创建,也不能销毁线程的run loop。,Core Foundation根据需要为你创建。通过CFRunLoopGetMain  你可以获得当前线程的runloop。调用lCFRunLoopRun 来使当前线程的run loop以默认模式运行起来,直到调用CFRunLoopStop 来停止runloop。你也可以调用CFRunLoopRunInMode 来使当前线程的runloop以指定模式运行起来一段时间或者直到run loop被停止。 runloop只能在请求模式至少有一个source或者timer可监控的情况下运行起来。 

run loop可以递归运行,你可以在任何run loop标注内部调用CFRunLoopRun 或 CFRunLoopRunInMode,还可以创建嵌套run loop,并在当前线程调用栈激活,在标注内并没有限制在那种模式可以运行。 你可以创建另一个runloop,激活运行在任何可行的run loop模式,包括任何已经运行在调用堆栈中的更高的模式。

Cocoa 和 Carbon 每个都是建立在 CFRunLoop上来实现它们自己更高级别的事件循环。当编写一个 Cocoa 或者 Carbon应用,你可以添加你的sources、timer和observers到它们的runloop对象中。你的对象将会作为常规应用事件循环的一部分来得到监控。使用 NSRunLoop实例方法 getCFRunLoop  来获得对应应于cocoa runloop的CFRunLoop,在carbon应用中使用 GetCFRunLoopFromEventLoop 函数 

 

例子1,在NSThread创建Run Loop:

IPhone多线程编程提议用NSOperation和NSOperationQueue,这个接口苹果已经封装的很具有自动化的效果,对开发者来说,更简单易用。 

但是有些情况下,我们还是在运行一些长线任务或者复杂任务的时候,还是需要用到NSThread,这就需要为NSThread创建一个run loop. 

  1. //创建一个新的线程,其中object:nil部分可以作为selector的参数传递,在这里没有参数,设为nil  
  2. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(playerThread: ) object:nil];  
  3.   
  4. //开启线程,如果是利用NSOperation,只需要加入到NSOperationQueue里面去就好了,queue自己会在合适的时机执行线程,而不需要程序员自己去控制。  
  5. [thread start];   
  6.   
  7. - (void) playerThread:id)unused   
  8. {   
  9.     currentLoop = CFRunLoopGetCurrent();//子线程的runloop引用   
  10.     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];//为子线程创建自动释放池   
  11.     //run loop   
  12.     [self initPlayer];  
  13.     //CFRunLoopRun,Runs the current thread’s CFRunLoop object in its default mode indefinitely.   
  14.     CFRunLoopRun();   
  15.     //run loop,这里就会停住了。   
  16.     [pool release];   
  17. }   
  18. // 实现一个timer,用于检查子线程的工作状态,并在合适的时候做任务切换。或者是合适的时候停掉  
  19. // 自己的run loop  
  20. -(void) initPlayer   
  21. {   
  22.     // 在这里你可以初始化一个工作类,比如声音或者视频播放   
  23.     NSTimer *stateChange = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self  
  24.                                                           selector:@selector(checkState:) userInfo:nil repeats:YES];   
  25. }   
  26. -(void) checkState:(NSTimer*) timer   
  27. {   
  28.     if(需要退出自定义的线程了)   
  29.     {   
  30.         //释放子线程里面的资源  
  31.         //释放资源的代码....  
  32.         /*结束子线程任务 CFRunLoopStop,This function forces rl to stop running and  
  33.         return control to the function that called CFRunLoopRun or CFRunLoopRunInMode  
  34.         for the current run loop activation. If the run loop is nested with a callout 
  35.         from one activation starting another activation running, only the innermost 
  36.         activation is exited.*/  
  37.         CFRunLoopStop(currentLoop);   
  38.     }   
  39. }  

 

 


例子2,用Run Loop控制动画的过程: 

 #import "UIView-ModalAnimationHelper.h"  

  1.   
  2. @interface UIViewDelegate : NSObject  
  3. {  
  4.     CFRunLoopRef currentLoop;  
  5. }  
  6. @end  
  7.   
  8. @implementation UIViewDelegate  
  9. -(id) initWithRunLoop: (CFRunLoopRef)runLoop   
  10. {  
  11.     if (self = [super init]) currentLoop = runLoop;  
  12.     return self;  
  13. }  
  14.   
  15. -(void) animationFinished: (id) sender  
  16. {  
  17.     CFRunLoopStop(currentLoop);  
  18. }  
  19. @end  
  20.   
  21. @implementation UIView (ModalAnimationHelper)  
  22. + (void) commitModalAnimations  
  23. {  
  24.     CFRunLoopRef currentLoop = CFRunLoopGetCurrent();  
  25.       
  26.     UIViewDelegate *uivdelegate = [[UIViewDelegate alloc] initWithRunLoop:currentLoop];  
  27.     [UIView setAnimationDelegate:uivdelegate];  
  28.     [UIView setAnimationDidStopSelector:@selector(animationFinished:)];  
  29.     [UIView commitAnimations];  
  30.     CFRunLoopRun();  
  31.     [uivdelegate release];  
  32. }  
  33. @end  

 

 

//应用

 
  1. [UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];  
  2. [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];  
  3. [UIView setAnimationDuration:0.4f];  
  4. ......  
  5. [UIView commitModalAnimations];  

以上是关于RunLoop的主要内容,如果未能解决你的问题,请参考以下文章