標籤:style http color 使用 os io width for
A run loop for a given thread will wait until one or more of its input sources has some data or event, then fire the appropriate input handler(s) to process each input source that is "ready." After doing so, it will then return to its loop, processing input from various sources, and "sleeping" if there is no work to do. NSRunLoop is better than sleep because it allows the runloop to respond to events while you wait. If you just sleep your thread your app will block even if events arrive.
其實說的簡單點兒,NSRunLoop的本質是一個訊息機制的處理模式。系統級的RunLoop所示如下
關於 (BOOL) runMode:(NSString *)mode beforeDate:(NSDate *)date這個方法,具體的參數解釋如下:
1. mode指定runloop模式來處理輸入源。
2. 當date設定為[NSDate distantFuture](將來,基本不會到達的時間),所以除非處理其他輸入源結束,否則永不退出處理暫停當前處理的流程。
一般情況下,當我們使用NSRunLoop的時候,代碼都如下所示:
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]];
} while (!done);
在上面的代碼中,參數done為NO的時候,當前runloop會一直接收處理其他輸入源,處理輸入源之後會再回到runloop中等待其他的輸入源;除非done為NO,否則當前流程一直再runloop中,我們用下面的一個執行個體來詳細的解釋如何使用NSRunLoop。
- (void) downloadImage:(NSString*)url{
_subThreed = [NSThread currentThread];
NSAutoreleasePool *uploadPool = [[NSAutoreleasePool alloc] init];
done = NO;
characterBuffer = [NSMutableData data];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURLURLWithString:url]];
connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (connection != nil) {
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]];
} while (!done);
}
imageView.image = [UIImage imageWithData:characterBuffer];
// Release resources used only in this thread.
connection = nil;
[uploadPool release];
uploadPool = nil;
_subThreed = nil;
}
上面這段代碼特別有意思的地方在於,當執行個體化一個connection之後,馬上執行download圖片的代理事件,同時當前進程進NSRunLoop,在這個過程中,可以響應某些輸入源,比如操作介面上的控制項:點擊某個button,滑動等等事件,這些事件都可以順利執行。直到done為YES的時候,這個NSRunLoop才會結束(在具體的代碼中,我們可以在connection的didFailWithError 或者connectionDidFinishLoading代理事件中設定),結束NSRunLoop後, 代碼會繼續執行下面一行:
imageView.image = [UIImage imageWithData:characterBuffer];
下面是代碼在NSRunLoop中處理外部輸入源的時候callstack,我們可以清楚的看見這裡比較明顯的有兩個thread,其中之一是NSRunLoop(thread 13),而另外的一個是外部輸入源的thread(thread 1)。
所以說到這裡,我的理解是上面的NSRunLoop代碼和非同步網路訪問比較類似,不同點在於NSRunLoop在connection結束後會重設迴圈條件,這樣就結束NSRunLoop的運行,然後NSRunLoop後面的代碼就繼續執行,而非同步網路訪問則需要在connection的connectionDidFinishLoading裡面執行後續的代碼。為什麼這樣做呢,其實道理很簡單,為了讓整個代碼的邏輯更加清楚,如果我們沒有這樣的一個runloop的話,就不得不在子線程的結束的地方,加上imageView.image = [UIImage imageWithData:characterBuffer];(這個有可能是介面操作),則顯得代碼不夠緊湊,容易出錯。