iPhone應(yīng)用開發(fā)之NSRunLoop概述
iPhone應(yīng)用開發(fā)中關(guān)于NSRunLoop的概述是本文要介紹的內(nèi)容,NSRunLoop是一種更加高明的消息處理模式,他就高明在對消息處理過程進行了更好的抽象和封裝,這樣才能是的你不用處理一些很瑣碎很低層次的具體消息的處理,在NSRunLoop中每一個消息就被打包在input source或者是timer source中了,來看詳細(xì)內(nèi)容。
1.什么是NSRunLoop
我們會經(jīng)??吹竭@樣的代碼:
- - (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];
- }
這段代碼很神奇的,因為他會“暫停”代碼運行,而且程序運行不會因為這里有一個while循環(huán)而受到影響。在[progress setHidden:NO]執(zhí)行之后,整個函數(shù)想暫停了一樣停在循環(huán)里面,等loadPageInBackground里面的操作都完成了以后才讓[progress setHidden:YES]運行。這樣做就顯得簡介,而且邏輯很清晰。如果你不這樣做,你就需要在loadPageInBackground里面表示load完成的地方調(diào)用[progress setHidden:YES],顯得代碼不緊湊而且容易出錯。
那么具體什么是NSRunLoop呢?其實NSRunLoop的本質(zhì)是一個消息機制的處理模式。如果你對vc++編程有一定了解,在windows中,有一系列很重要的函數(shù)SendMessage,PostMessage,GetMessage,這些都是有關(guān)消息傳遞處理的API。
但是在你進入到Cocoa的編程世界里面,我不知道你是不是走的太快太匆忙而忽視了這個很重要的問題,Cocoa里面就沒有提及到任何關(guān)于消息處理的API,開發(fā)者從來也沒有自己去關(guān)心過消息的傳遞過程,好像一切都是那么自然,像大自然一樣自然?在Cocoa里面你再也不用去自己定義WM_COMMAD_XXX這樣的宏來標(biāo)識某個消息,也不用在switch-case里面去對特定的消息做特別的處理。難道是Cocoa里面就沒有了消息機制?答案是否定的,只是Apple在設(shè)計消息處理的時候采用了一個更加高明的模式,那就是RunLoop。
2. NSRunLoop工作原理
接下來看一下NSRunLoop具體的工作原理,首先是官方文檔提供的說法,看圖:
通過所有的“消息”都被添加到了NSRunLoop中去,而在這里這些消息并分為“input source”和“Timer source” 并在循環(huán)中檢查是不是有事件需要發(fā)生,如果需要那么就調(diào)用相應(yīng)的函數(shù)處理。為了更清晰的解釋,我們來對比VC++和iOS消息處理過程。
VC++中在一切初始化都完成之后程序就開始這樣一個循環(huán)了(代碼是從戶sir mfc程序設(shè)計課程的slides中截?。?/p>
- 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);
- }
- }
- }
可以看到在GetMessage之后就去分發(fā)處理消息了,而iOS中main函數(shù)中只是調(diào)用了UIApplicationMain,那么我們可以介意猜出UIApplicationMain在初始化完成之后就會進入這樣一個情形:
- int UIApplicationMain(...){
- ...
- while(running){
- [NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
- }
- ...
- }
所以在UIApplicationMain中也是同樣在不斷處理runloop才是的程序沒有退出。剛才的我說了NSRunLoop是一種更加高明的消息處理模式,他就高明在對消息處理過程進行了更好的抽象和封裝,這樣才能是的你不用處理一些很瑣碎很低層次的具體消息的處理,在NSRunLoop中每一個消息就被打包在input source或者是timer source中了,當(dāng)需要處理的時候就直接調(diào)用其中包含的相應(yīng)對象的處理函數(shù)了。
所以對外部的開發(fā)人員來講,你感受到的就是,把source/timer加入到runloop中,然后在適當(dāng)?shù)臅r候類似于[receiver action]這樣的事情發(fā)生了。甚至很多時候,你都沒有感受到整個過程前半部分,你只是感覺到了你的某個對象的某個函數(shù)調(diào)用了。
比如在UIView被觸摸時會用touchesBegan/touchesMoved等等函數(shù)被調(diào)用,也許你會想,“該死的,我都不知道在那里被告知有觸摸消息,這些處理函數(shù)就被調(diào)用了???”所以,消息是有的,只是runloop已經(jīng)幫你做了!為了證明我的觀點,我截取了一張debug touchesBegan的call stack,有圖有真相,如圖:
現(xiàn)在會過頭來看看剛才的那個會“暫停”代碼的例子,有沒有更加深入的認(rèn)識了呢?
小結(jié):iPhone應(yīng)用開發(fā)之NSRunLoop概述的內(nèi)容介紹完了,希望本文對你有所幫助!