最近這幾天一直在研究RunLoop(它是什么就不延伸了,網(wǎng)上教程很多),總算有點(diǎn)心得,今天主要是記錄下在研究過(guò)程中所寫(xiě)的demo。
本文主要是記錄2個(gè)地方:
- RunLoop與NSTimer的結(jié)合
- RunLoop與NSURLConnection的結(jié)合
首先先討論第一個(gè),默認(rèn)情況下NSTimer被創(chuàng)建好之后,是運(yùn)行中Default Mode下的。所以當(dāng)頁(yè)面中有Scroll事件和Timer共存時(shí),一旦Scroll事件正常影響,那么Timer的事件則會(huì)被阻塞得不到任何反應(yīng)!

我們從上圖可以看圖,在2s-4s之間,我拖動(dòng)了UITableView,頂部的數(shù)值并未變化!直到第5s放開(kāi)拖動(dòng)后,數(shù)值會(huì)延續(xù)+1,所以我們可以簡(jiǎn)單的總結(jié):當(dāng)拖動(dòng)時(shí),Timer被凍結(jié)了;松開(kāi)時(shí),Timer被重新喚醒,然后執(zhí)行!
其實(shí)這個(gè)場(chǎng)景用得相對(duì)較少,但是有一個(gè)場(chǎng)景我想可能很多人都碰到過(guò)或可能即將碰到!那就是:
添加商品到購(gòu)物車(chē)后,倒計(jì)時(shí)15分鐘(假設(shè)),如果15分鐘結(jié)束之后,自動(dòng)會(huì)從購(gòu)物車(chē)移除。
我相信很多做購(gòu)物App的人都碰到過(guò)類(lèi)似的需求,大部分人都會(huì)首先使用NSTimer(當(dāng)然還有其他方式)來(lái)每隔1秒判斷一次,這時(shí)候我們?nèi)绻恢繰unLoop的機(jī)制的話,那么我們?cè)陬l繁拖動(dòng)UITableView時(shí)就會(huì)出現(xiàn)時(shí)間差值(因?yàn)橥蟿?dòng)凍結(jié)了NSTimer,所以導(dǎo)致時(shí)間根本就不是15分鐘)!
那么如果解決這個(gè)問(wèn)題呢?大招來(lái)了~~~
- 更改RunLoop運(yùn)行Mode
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
或者
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
- 將NSTimer放到新的線程(非UI線程)中
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];
[thread start];
- (void)newThread{
@autoreleasepool{
//在當(dāng)前Run Loop中添加timer,模式是默認(rèn)的NSDefaultRunLoopMode
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(incrementCounter:) userInfo: nil repeats:YES];
//開(kāi)始執(zhí)行新線程的Run Loop,如果不啟動(dòng)run loop,timer的事件是不會(huì)響應(yīng)的
[[NSRunLoop currentRunLoop] run];
}
}
OK啦,一旦這樣設(shè)置之后,NSTimer的事件影響就不會(huì)被凍結(jié)了!

然后我們來(lái)討論一下NSURLConnection,NSURLConnection默認(rèn)情況下也是在Default Mode下。
假設(shè)我們有一個(gè)UITableView,UITableView上面有很多UITableViewCell,UITableViewCell上面有一個(gè)UIImageView(你可以想象QQ的聊天頁(yè)面)。這時(shí)候一般我們的需求都是那個(gè)UIImageView的圖片需要你從網(wǎng)絡(luò)上下載,并且異步,下載成功之后更新到UIImageView上!??!
實(shí)際上這個(gè)時(shí)候我們就會(huì)碰到問(wèn)題,因?yàn)槲覀兊腢ITableView是可以任意拖動(dòng)的,所以如果不更改NSURLConnection的運(yùn)行模式,那么在拖動(dòng)過(guò)程中就會(huì)凍結(jié)掉NSURLConnection的RunLoop。這時(shí)候就會(huì)產(chǎn)生2個(gè)不好的想象:
- UIImageView遲遲得不到圖片數(shù)據(jù),從而導(dǎo)致遲遲無(wú)法設(shè)置image
- NSURLConnection是有timeout的,所以如果被凍結(jié)時(shí)間過(guò)長(zhǎng),可能會(huì)導(dǎo)致結(jié)果被拋棄
解決此問(wèn)題的代碼如下:
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];