NSRunLoop的进一步理解
2011-09-17 00:57
246 查看
先说一下我自己的理解:
iOS的应用程序里面,程序启动后会有一个
main thread 开始执行 main() -> UIApplicationMain() 函数,然后为这个 main thread 设置了一个 NSRunLoop 对象,每个线程只可以关联一个 NSRunLoop 对象的,具体怎么关联的目前还不清楚,可以认为 NSThread 和 NSRunLoop 是一对一的关系。我个人理解的NSRunLoop就是:可以给
NSRunLoop 设置一堆的 Input Sources 和 Observers,它们之间通过一个叫 “Run Loop Mode”的东西关联起来,实际上就是一个 NSString 而已, 对于 main thead 的 RunLoop, 就开始不断的的轮询每一个 input source,看看有没有 event 发生,如果有event,就给相关的observer 发送 notification, 给observer去处理event, 例如当发生的 touch event 的时候。先想到这么多,欢迎大家指正或补充!
我们会经常看到这样的代码:1 2 3 4 5 6 7 8 9 10 | - (IBAction)start:(id)sender { pageStillLoading = YES; [NSThread detachNewThreadSelector:@selector(loadPageInBackground:)toTarget:self withObject:nil]; [progress setHidden:NO]; while (pageStillLoading) { [NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } [progress setHidden:YES]; } |
那么具体什么是NSRunLoop呢?其实NSRunLoop的本质是一个消息机制的处理模式。如果你对vc++编程有一定了解,在windows中,有一系列很重要的函数SendMessage,PostMessage,GetMessage,这些都是有关消息传递处理的API。但是在你进入到Cocoa的编程世界里面,我不知道你是不是走的太快太匆忙而忽视了这个很重要的问题,Cocoa里面就没有提及到任何关于消息处理的API,开发者从来也没有自己去关心过消息的传递过程,好像一切都是那么自然,像大自然一样自然?在Cocoa里面你再也不用去自己定义WM_COMMAD_XXX这样的宏来标识某个消息,也不用在switch-case里面去对特定的消息做特别的处理。难道是Cocoa里面就没有了消息机制?答案是否定的,只是Apple在设计消息处理的时候采用了一个更加高明的模式,那就是RunLoop。
2. NSRunLoop工作原理
接下来看一下NSRunLoop具体的工作原理,首先是官方文档提供的说法,看图:
![](http://xubenyang.me/wp-content/uploads/2010/12/NSRunLoop-Infrastructure.png)
通过所有的“消息”都被添加到了NSRunLoop中去,而在这里这些消息并分为“input source”和“Timer source” 并在循环中检查是不是有事件需要发生,如果需要那么就调用相应的函数处理。为了更清晰的解释,我们来对比VC++和iOS消息处理过程。
VC++中在一切初始化都完成之后程序就开始这样一个循环了(代码是从户sir mfc程序设计课程的slides中截取):
1 2 3 4 5 6 7 8 9 | int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ ... while (GetMessage(&msg, NULL, 0, 0)){ if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){ TranslateMessage(&msg); DispatchMessage(&msg); } } } |
1 2 3 4 5 6 7 | int UIApplicationMain(...){ ... while(running){ [NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } ... } |
action]这样的事情发生了。甚至很多时候,你都没有感受到整个过程前半部分,你只是感觉到了你的某个对象的某个函数调用了。比如在UIView被触摸时会用touchesBegan/touchesMoved等等函数被调用,也许你会想,“该死的,我都不知道在那里被告知有触摸消息,这些处理函数就被调用了!?”所以,消息是有的,只是runloop已经帮你做了!为了证明我的观点,我截取了一张debug touchesBegan的call stack,有图有真相:
![](http://xubenyang.me/wp-content/uploads/2010/12/runloop-callstack.png)
现在会过头来看看刚才的那个会“暂停”代码的例子,有没有更加深入的认识了呢?
相关文章推荐
- IOS NSRunLoop的进一步理解
- iPhone开发之NSRunLoop的进一步理解
- iPhone开发之NSRunLoop的进一步理解
- 转载:iPhone开发之NSRunLoop的进一步理解
- NSRunLoop的进一步理解
- NSRunLoop的进一步理解
- iPhone开发之NSRunLoop的进一步理解
- iPhone开发之NSRunLoop的进一步理解
- NSRunLoop的进一步理解
- NSRunLoop的进一步理解
- iPhone开发之NSRunLoop的进一步理解
- iOS开发之NSRunLoop的进一步理解
- iPhone开发之NSRunLoop的进一步理解
- NSRunLoop的进一步理解
- NSRunLoop的进一步理解
- android 关于启动模式的进一步理解
- 关于iOS 类扩展Extension的进一步深层理解
- 对保护模式及模式及其之间的转换的进一步理解
- tensorflow实现MNIST数据集识别---进一步理解
- NSRunLoop的理解