回顧一下椭蹄,Run Loop就是個監(jiān)聽事件的循環(huán)庐杨,會不停的檢查它的事件源(Timer和Input Source)有沒有事件發(fā)生,如果有事件發(fā)生就處理事件或者調(diào)用事件的處理方法骤公。
坑一
在線程中添加Timer時呐粘,肯定需要先生成Timer對象啦满俗,有類方法也有實例方法,如果是使用scheduledTimerWith***接口生成的Timer對象作岖,會自動添加到當前線程的NSDefaultRunLoopMode中唆垃;如果是其他接口生成的Timer對象,則需要用-addTimer:forMode
添加Timer痘儡,這樣做的好處是可以指定添加Timer的Run Loop以及模式辕万。
坑二
如果Run Loop中添加的是Timer而沒有其他Input Source,而這個Timer只運行一次沉删,那么Timer事件觸發(fā)后Timer事件源就會從Run Loop刪除渐尿,那么再運行Run Loop就會立刻返回;同時Timer事件觸發(fā)是不會讓Run Loop返回的矾瑰,即使使用CF層的CFRunLoopRef運行接口SInt32 CFRunLoopRunInMode (mode, seconds, returnAfterSourceHandled);
運行Run Loop砖茸,其第三個參數(shù)為YES,Timer事件觸發(fā)仍然不會導(dǎo)致當前Run Loop的運行返回殴穴。
坑三
如果是使用NSRunLoop凉夯,有三個運行的接口:
//運行 NSRunLoop,運行模式為默認的NSDefaultRunLoopMode模式采幌,沒有超時限制- (void)run;//運行 NSRunLoop: 參數(shù)為運行模式劲够、時間期限,返回值為YES表示是處理事件后返回的休傍,NO表示是超時或者停止運行導(dǎo)致返回的征绎。[Update]: 感謝網(wǎng)友olo的提醒:返回值只有在RunLoop沒有運行的情況下才返回NO。比如:1)沒有添加輸入源和定時器源 2)mode為NSRunLoopCommonModes 或UITrackingRunLoopMode 等“非法”參數(shù)磨取。如果超時的話返回YES人柿,即使limitDate的初始值小于當前的Date柴墩,RunLoop也會執(zhí)行一次然后馬上返回YES。- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;//運行 NSRunLoop: 參數(shù)為運時間期限凫岖,運行模式為默認的NSDefaultRunLoopMode模式- (void)runUntilDate:(NSDate *)limitDate;
建議是使用第二個接口來運行拐邪,因為它能夠設(shè)置Run Loop的運行參數(shù)最多,而且最重要的是可以使用CFRunLoopStop(runLoopRef)來停止Run Loop的運行隘截,而第一個和第三個接口無法使用CFRunLoopStop(runLoopRef)來停止Run Loop的運行。
坑四
在使用NSURLConnection或者NSStream時汹胃,需要考慮到Run Loop的問題婶芭,默認情況下這兩個對象生成后都是運行在當前線程的NSDefaultRunLoopMode模式的,如果是在主線程着饥,那么在滾動ScrollView或者TableView時犀农,主線程的Run Loop會運行在UITrackingRunLoopMode模式,那么NSURLConnection或者NSStream的回調(diào)就無法運行宰掉。因此最好是指定NSURLConnection或NSStream在Run Loop中的運行模式呵哨,兩者有相同的接口- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
來設(shè)置NSURLConnection和NSStream的Run Loop以及模式,而且設(shè)置的Mode要設(shè)置為NSRunLoopCommonModes轨奄,因為NSRunLoopCommonModes默認會包含NSDefaultRunLoopMode和UITrackingRunLoopMode孟害,這樣無論Run Loop運行在哪個模式,都可以保證NSURLConnection或者NSStream的回調(diào)可以被調(diào)用挪拟。另外如果是在子線程中你設(shè)置了自定義的Run Loop模式挨务,還可以用接口CFRunLoopAddCommonMode(runLoopRef, mode)
添加到NSRunLoopCommonModes。
不過NSURLConnection的使用有點特殊玉组,必須使用它的designated initializer - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately
生成NSURLConnection對象谎柄,而且第三個參數(shù)是否立刻啟動NSURLConnection要設(shè)置為NO,之后再用- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
設(shè)置Run Loop與模式惯雳,再調(diào)用[NSURLConnectionObject start]
啟動朝巫。如果是其他接口生成NSURLConnection,用- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
設(shè)置Run Loop和mode都不會起作用石景。