關(guān)于NSTimer

關(guān)于NSTimer

在工作中經(jīng)常會做一些延時(shí)任務(wù),或者周期性任務(wù),有時(shí)候也需要對取消延時(shí)任務(wù)操作。

延時(shí)任務(wù)一般有三種
  • NSObject的
 -(void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
  • 使用NSTimer的一些函數(shù)
  +(NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
  • 使用GCD的一些函數(shù)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{});


> 如果這個(gè)任務(wù)不需要撤銷,使用GCD是最好的選擇
如果需要有撤銷操作,就不能使用GCD,使用NSObject的函數(shù)或者使用NSTimer需要注意一些細(xì)節(jié)

* 必須有一個(gè)活躍的RunLoop, performSelector和NSTimer的一些函數(shù)都是基于RunLoop的,主線程的RunLopp是默認(rèn)啟動的,如果放在子線程創(chuàng)建必須手動啟動子線程的RunLoop。
* NSTimer的創(chuàng)建和撤銷需要放在同一個(gè)線程操作,performSelector的創(chuàng)建與撤銷必須在同一個(gè)線程操作。
* 有內(nèi)存泄露的潛在風(fēng)險(xiǎn),scheduledTimerWithTimeInterval函數(shù)會對target進(jìn)行強(qiáng)引用,而NSTimer會被當(dāng)前的runloop強(qiáng)引用,只有當(dāng)調(diào)用NSTimer的invalidate才能解除掉這個(gè)強(qiáng)引用,performSelector也同樣會對target進(jìn)行強(qiáng)引用,必須手動取消才可以解除這個(gè)強(qiáng)引用,當(dāng)我們創(chuàng)建一個(gè)NSTimer的時(shí)候,我們在當(dāng)前對象的dealloc函數(shù)中invalidate這個(gè)timer,看似合理,但是dealloc永遠(yuǎn)不會被調(diào)用,造成了內(nèi)存泄露

> 看下蘋果對NSTimer的invalidate函數(shù)介紹
> Discussion
>
This method is the only way to remove a timer from an NSRunLoop object. The NSRunLoop object removes its strong reference to the timer, either just before the invalidate method returns or at some later point.
>
If it was configured with target and user info objects, the receiver removes its strong references to those objects as well.
>
Special Considerations
>
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.

只有這個(gè)函數(shù)才能從runloop中刪除這個(gè)定時(shí)器。

>
所以我們使用NSTimer會考慮timer何時(shí)釋放的問題,我們一般的做法是在頁面顯示的時(shí)候啟動這個(gè)定時(shí)器,頁面消失的時(shí)候停止這個(gè)定時(shí)器

但是有的時(shí)候有需求,需要定時(shí)器不要停止,我們從當(dāng)前頁面push到另外一個(gè)頁面的時(shí)候 定時(shí)器不停止。如果停止定時(shí)器放在viewWillDisappear函數(shù)中時(shí),push到其他頁面定時(shí)器一樣會停止。
>
保證Timer一定會被停止,可以手動停止,就是調(diào)用invalidate,可以在頁面退出的時(shí)候手動的去invalidate,(在back的時(shí)候,等等)。
只前遇到這種需求,對Timer做了一個(gè)簡單的封裝,先看代碼

BFSTimerextension.h

import <Foundation/Foundation.h>

@protocol BFSTimerextensionDelegate <NSObject>
/**
定時(shí)器調(diào)用代理函數(shù)
/
-(void)timerfucntionCall;
@end
@interface BFSTimerextension : NSObject
@property(nonatomic,weak) id<BFSTimerextensionDelegate> delegate;
/
*
啟動一個(gè)定時(shí)器
@param timeInterval 間隔時(shí)間
@param repeats 是否重復(fù)
/
-(void)startTimer:(NSTimeInterval)timeInterval repeats:(BOOL)repeats;
/
*
停止這個(gè)定時(shí)器
*/
-(void)stopTimer;
@end


   BFSTimerextension.m
   

import "BFSTimerextension.h"

@interface BFSTimerextension()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation BFSTimerextension
-(void)dealloc
{
NSLog(@"被釋放");
}

-(void)startTimer:(NSTimeInterval)timeInterval repeats:(BOOL)repeats
{
if(!_timer)
{
_timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(timerSelectCall) userInfo:nil repeats:repeats];
}
}

-(void)timerSelectCall
{
if(self.delegate && [self.delegate respondsToSelector:@selector(timerfucntionCall)])
{
[self.delegate timerfucntionCall];
}else{
[self.timer invalidate];
self.timer = nil;
}
}

-(void)stopTimer
{
if(self.timer)
{
[self.timer invalidate];
self.timer = nil;
}
}
@end



使用BFSTimerextension創(chuàng)建一個(gè)Timer  timer的tagret是BFSTimerextension,如果BFSTimerextension的delegate被釋放,timer直接釋放掉,我們不用在考慮timer什么時(shí)機(jī)停止的問題,

注:文中若有錯(cuò)誤,請指出,謝謝
代碼地址請點(diǎn)擊[這里](https://github.com/CharType/Timerextension)





 
 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • NSTimer使用方式 常用的創(chuàng)建方式有 1+ (NSTimer *)timerWithTimeInterval:...
    開發(fā)全靠xib閱讀 293評論 0 0
  • 想了解NSTimer的坑我們應(yīng)該先熟悉下NSTimer的原理也就是他是怎么實(shí)現(xiàn)定時(shí)器的 runloop處理三種事件...
    RFeng閱讀 834評論 0 2
  • NSTimer 一個(gè)計(jì)時(shí)器,不算常用但也算基礎(chǔ)。我想每個(gè)開發(fā)iOS都應(yīng)該知道,所以我一般會把他當(dāng)作一個(gè)面試題??梢?..
    jing091111閱讀 411評論 5 2
  • 面試中,經(jīng)常會問道 NSTimer 循環(huán)引用的問題。閑話少敘。下面來講講 NSTimer 為什么會造成循環(huán)引用? ...
    人話博客閱讀 1,519評論 0 53
  • 看一本說吃說喝的書,忽然想起了羊湯。曾經(jīng)有幾年,午飯還在單位吃時(shí),每個(gè)冬天,都要去喝幾回羊湯。 那時(shí),農(nóng)場那一帶除...
    鉛筆芒種閱讀 412評論 0 1

友情鏈接更多精彩內(nèi)容