開始前咱們先知道NSTimer是用來的干嘛的。
A timer waits until a certain time interval has elapsed and then fires,
sending a specified message to a target object.
從這里我們可以看出來,NSTimer就是我為了過一段時(shí)間想目標(biāo)發(fā)送一個(gè)消息,從而執(zhí)行一系列的操作。既然我們已經(jīng)知道用法。所以咱們先來個(gè)最簡單的用法
[NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(run:) userInfo:nil repeats:YES];
方法實(shí)現(xiàn)里直接打印helloworld就好,這里我就不再占用篇幅去寫了。自己去補(bǔ)就好。上面這個(gè)函數(shù)的意思就是每隔1.5秒執(zhí)行一次run方法。注意:如果repeats參數(shù)為NO時(shí),只會(huì)執(zhí)行一遍該方法。
接下來我們看看怎樣控制定時(shí)器的開關(guān)
[_timer setFireDate:[NSDate distantFuture]];
調(diào)用上面語句,定時(shí)器就會(huì)關(guān)閉
[_timer setFireDate:[NSDate distantPast]];
上面就是開啟定時(shí)器
關(guān)于NSTimer也不能說的太深,因?yàn)闋可娴揭恍﹔unloop的知識(shí)。大家有興趣的可以去研究一下。我也做過這方面的研究,只可惜研究尚欠,難等大雅之堂,今天就不跟大家分享,等我研究的小有成就的時(shí)候。在跟大家分享。
今天我在做AVPlayer的自定義過程中有要用到定時(shí)器,其中就涉及到runloop,今天我跟新博文不為談runloop的底層實(shí)現(xiàn),只為談涉及到NSTimer一些bug的解決方案;
問題假設(shè),我們需要程序定時(shí)做一件事,這個(gè)時(shí)候我們創(chuàng)建NSTimer
_timer = [NSTimer timerWithTimeInterval:1.5 target:self selector:@selector(nslog) userInfo:nil repeats:YES];
細(xì)心的同學(xué)會(huì)發(fā)現(xiàn),這個(gè)NSTimer不會(huì)被執(zhí)行,即使我們調(diào)用上面的開啟方法,也不會(huì)執(zhí)行。下面跟大家簡單談一下NSTimer的底層實(shí)現(xiàn)。
當(dāng)我們創(chuàng)建NSTimer后,只有將NSTimer放到一個(gè)事件循環(huán)鏈(eventloop)中,NSTimer才能一直執(zhí)行下去,iOS中我們實(shí)現(xiàn)的方法就是放到runloop中。所以我們想要讓上面創(chuàng)建的NSTimer執(zhí)行,我們就必須將NSTimer放到一個(gè)runloop鐘。我的解決方案是獲取當(dāng)前的runloop,然后將NSTimer放進(jìn)去。代碼如下
NSRunLoop *run = [NSRunLoop currentRunLoop];
[run addTimer:_timer forMode:NSRunLoopCommonModes];
或許大家會(huì)問為什么用第一個(gè)方法創(chuàng)建時(shí)能夠直接執(zhí)行那,我跟人的推測(cè),應(yīng)該運(yùn)用schedul創(chuàng)建的NSTimer,默認(rèn)會(huì)將當(dāng)前創(chuàng)建的NSTimer放到當(dāng)前的runloop中。
文章的最后我們說一下NSTimer的內(nèi)存釋放問題。因?yàn)镹STimer是需要加入runloop中,這就形成了一個(gè)典型的循環(huán)引用,所以我們必須顯示的釋放掉NSTimer,否則就會(huì)造成內(nèi)存泄漏。
特別強(qiáng)調(diào):
NSTimer的釋放不能放到dealloc中進(jìn)行,試問上面兩個(gè)哥們沒有停止,dealloc怎么執(zhí)行。所以這里一定要注意,不能講NSTimer放到dealloc中釋放。至于在哪釋放,根據(jù)自己需要的去釋放就好了。
[_timer invalidate];
_timer = nil;