http://blog.callmewhy.com/2015/07/06/weak-timer-in-ios/
今天了解到一個(gè)問(wèn)題,關(guān)于nstimer的問(wèn)題。一般來(lái)說(shuō)拆融,我們是這么創(chuàng)建一個(gè)timer的例子的:
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(printMessage:) userInfo:nil repeats:YES];
但是在實(shí)際運(yùn)用過(guò)程中染突,我們一般會(huì)遇到這樣子的情況,就是某一個(gè)頁(yè)面存在一個(gè)輪播圖姻僧,下方有一個(gè)tableview规丽。當(dāng)我們開(kāi)始滑動(dòng)tableview的時(shí)候,輪播圖會(huì)停止運(yùn)行撇贺,這個(gè)是為什么呢赌莺?在開(kāi)啟一個(gè)NSTimer實(shí)質(zhì)上是在當(dāng)前的runloop中注冊(cè)了一個(gè)新的事件源,而當(dāng)scrollView滾動(dòng)的時(shí)候松嘶,當(dāng)前的MainRunLoop是處于UITrackingRunLoopMode的模式下艘狭,在這個(gè)模式下,是不會(huì)處理NSDefaultRunLoopMode的消息(因?yàn)镽unLoop Mode不一樣)翠订,要想在scrollView滾動(dòng)的同時(shí)也接受其它runloop的消息巢音,我們需要改變兩者之間的runloopmode.
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
通過(guò)這個(gè)方式更改runloopmode。
PS:在http異步通信的模塊中也有可能碰到這樣的問(wèn)題尽超,就是在向服務(wù)器異步獲取圖片數(shù)據(jù)通知主線程刷新tableView中的圖片時(shí)官撼,在tableView滾動(dòng)沒(méi)有停止或用戶手指停留在屏幕上的時(shí)候,圖片一直不會(huì)出來(lái)似谁,這個(gè)是為什么呢傲绣?
針對(duì)NSTimer存在一個(gè)invalidate來(lái)把當(dāng)前的timer對(duì)象注銷,不過(guò)這個(gè)方法寫在哪里呢巩踏?可不可以寫在delloc方法里面呢斜筐?如果有人要說(shuō)arc情況下沒(méi)有delloc的話,請(qǐng)去小屋面壁吧蛀缝。正常來(lái)說(shuō)當(dāng)一個(gè)對(duì)象銷毀的時(shí)候顷链,會(huì)調(diào)用delloc方法(arc情況下不需要調(diào)用[supper delloc])。如果我們把[_timer invalidate];
寫在delloc里面會(huì)出現(xiàn)什么情況呢屈梁?發(fā)現(xiàn)根本不執(zhí)行這個(gè)delloc方法嗤练。
原因是Timer添加到Runloop的時(shí)候榛了,會(huì)被Runloop強(qiáng)引用:
Note in particular that run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
然后Timer又會(huì)有一個(gè)對(duì)Target的強(qiáng)引用(也就是 self ):
Target is the object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to target until it (the timer) is invalidated.
也就是說(shuō)NSTimer強(qiáng)引用了self,導(dǎo)致self一直不能被釋放掉煞抬,所以也就走不到self的dealloc里霜大。這樣子的循環(huán)引用導(dǎo)致了timer釋放不掉,self釋放不掉革答。但是战坤,其實(shí)不是所有的target都是強(qiáng)引用的,正常來(lái)說(shuō):
Control objects do not (and should not) retain their targets.
在考慮循環(huán)引用的時(shí)候残拐,target的問(wèn)題要針對(duì)其特定的點(diǎn)途茫。
在invalidate方法的文檔里還有這這樣一段話:
You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
NSTimer在哪個(gè)線程創(chuàng)建就要在哪個(gè)線程停止,否則會(huì)導(dǎo)致資源不能被正確的釋放溪食∧也罚看起來(lái)各種坑還不少。
如何解決這個(gè)問(wèn)題呢错沃?當(dāng)我們遇到這種循環(huán)引用引起的問(wèn)題時(shí)栅组,打破某一個(gè)引用就可以了。具體實(shí)現(xiàn)就看別人的東西吧