NSTimer 与 Run loop Modes
一.NSRunLoop
在Cocoa中,每個線程(NSThread)對象中內(nèi)部都有一個run loop(NSRunLoop)對象用來循環(huán)處理輸入事件,處理的事件包括兩類,一是來自Input sources的異步事件,一是來自Timer sources的同步事件;
run Loop在處理輸入事件時會產(chǎn)生通知,可以通過Core Foundation向線程中添加run-loop observers來監(jiān)聽特定事件,以在監(jiān)聽的事件發(fā)生時做附加的處理工作。
每個run loop可運行在不同的模式下,一個run loop mode是一個集合,其中包含其監(jiān)聽的若干輸入事件源,定時器,以及在事件發(fā)生時需要通知的run loop observers。運行在一種mode下的run loop只會處理其run loop mode中包含的輸入源事件,定時器事件,以及通知run loop mode中包含的observers。
Cocoa中的預(yù)定義模式有:
- Default模式
定義:NSDefaultRunLoopMode?(Cocoa)?kCFRunLoopDefaultMode?(Core Foundation)
描述:默認模式中幾乎包含了所有輸入源(NSConnection除外),一般情況下應(yīng)使用此模式。 - Connection模式
定義:NSConnectionReplyMode(Cocoa)
描述:處理NSConnection對象相關(guān)事件,系統(tǒng)內(nèi)部使用,用戶基本不會使用。 - Modal模式
定義:NSModalPanelRunLoopMode(Cocoa)
描述:處理modal panels事件。 - Event tracking模式
定義:UITrackingRunLoopMode(iOS) NSEventTrackingRunLoopMode(cocoa)
描述:在拖動loop或其他user interface tracking loops時處于此種模式下,在此模式下會限制輸入事件的處理。例如,當(dāng)手指按住UITableView拖動時就會處于此模式。 - Common模式
定義:NSRunLoopCommonModes?(Cocoa)?kCFRunLoopCommonModes?(Core Foundation)
描述:這是一個偽模式,其為一組run loop mode的集合,將輸入源加入此模式意味著在Common Modes中包含的所有模式下都可以處理。在Cocoa應(yīng)用程序中,默認情況下Common Modes包含default modes,modal modes,event Tracking modes.可使用CFRunLoopAddCommonMode方法想Common Modes中添加自定義modes。
獲取當(dāng)前線程的run loop mode
NSString* runLoopMode = [[NSRunLoop currentRunLoop] currentMode];二.NSTimer、NSURLConnection與UITrackingRunLoopMode
NSTimer與NSURLConnection默認運行在default mode下,這樣當(dāng)用戶在拖動UITableView處于UITrackingRunLoopMode模式時,NSTimer不能fire,NSURLConnection的數(shù)據(jù)也無法處理。
NSTimer的例子:
在一個UITableViewController中啟動一個0.2s的循環(huán)定時器,在定時器到期時更新一個計數(shù)器,并顯示在label上。
在正常情況下,可看到每隔0.2s,label上顯示的數(shù)字+1,但當(dāng)你拖動或按住tableView時,label上的數(shù)字不再更新,當(dāng)你手指離開時,label上的數(shù)字繼續(xù)更新。當(dāng)你拖動UItableView時,當(dāng)前線程run loop處于UIEventTrackingRunLoopMode模式,在這種模式下,不處理定時器事件,即定時器無法fire,label上的數(shù)字也就無法更新。
解決方法,一種方法是在另外的線程中處理定時器事件,可把Timer加入到NSOperation中在另一個線程中調(diào)度;還有一種方法時修改Timer運行的run loop模式,將其加入到UITrackingRunLoopMode模式或NSRunLoopCommonModes模式中。
即
或
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];NSURLConnection也是如此,見SDWebImage中的描述,以及SDWebImageDownloader.m代碼中的實現(xiàn)。修改NSURLConnection的運行模式可使用scheduleInRunLoop:forMode:方法。
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]autorelease]; [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [connection start];參考:
Threading Programming Guide – Run Loops
NSRunLoop Class Reference
NSURLConnection Class Reference
NSTimer Class Reference
CFRunLoop wiki
SDWebImage
TestButtonDown
NSTimerDoesntRunWhenMenuClicked
?
http://www.winddisk.com/2012/06/29/nstimer_run_loop_modes/
?
http://blog.csdn.net/jasonblog/article/details/7854693
轉(zhuǎn)載于:https://www.cnblogs.com/Piosa/archive/2012/10/30/2746652.html
總結(jié)
以上是生活随笔為你收集整理的NSTimer 与 Run loop Modes的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用Chrome与迅雷下载斗鱼录播视频
- 下一篇: vi和vim命令行编辑器命令