NSTimer的理解

NSTimer的定義

A timer that fires after a certain time interval has elapsed, sending a specified message to a target object.
簡單理解就是在一定的時間間隔后向指定對象發(fā)送指定消息衰絮。

NSTimer的調(diào)用方式

一募狂、自動加入NSRunLoop

方法名以scheduled開頭的均不需要手動加入NSRunLoop
方法有三個:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block

二脖旱、需要手動加入NSRunLoop

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block

重點參數(shù)解析

參數(shù):target

The object to which to send the message specified by aSelector when the timer fires. 
The timer maintains a strong reference to this object until it (the timer) is invalidated.

當timer開啟時饲嗽,消息的reciver烧给。NSTimer會強引用target直到(the timer) invalidated.

參數(shù):userInfo

Custom user info for the timer.

The timer maintains a strong reference to this object until it (the timer) is invalidated. This parameter may be nil.

自定義的額外數(shù)據(jù)。和target一樣喝噪,NSTimer會強引用userInfo直到(the timer) invalidated.

參數(shù):repeats

If YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires.

repeats為YES時,會重復執(zhí)行selector方法直到timer invalidated為止指么。
repeats為NO時, timer會在fires后被置為invalidated酝惧。
注意:以上說明,repeats為YES時伯诬,要想截止timer晚唇,需要調(diào)用[timer invalidate]方法,而repeats為NO時盗似,系統(tǒng)自動在fires后調(diào)用[timer invalidate]方法哩陕。

- (void)invalidate;

Stops the timer from ever firing again and requests its removal from its run loop.

停止timer,并請求從其運行循環(huán)中刪除它赫舒。

This method is the only way to remove a timer from an [NSRunLoop
](apple-reference-documentation://hclPs8uY7g) object. The NSRunLoop
 object removes its strong reference to the timer, either just before the [invalidate
](apple-reference-documentation://hcnIKt1Jb9) 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.

該方法是從NSRunLoop對象中刪除timer的唯一方法悍及。 NSRunLoop對象刪除其對定時器的強引用,就在invalidate方法返回之前或稍后一點接癌。
如果配置了target和userInfo對象心赶,timer也會刪除其對這些對象的強引用。

常說的循環(huán)引用

1, self強引用timer對象缺猛。

即如下方式:

self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerSelector) userInfo:nil repeats:YES];

對象引用圖:

6B6B7362-DC06-41AE-AA1C-BF9ABCDD28AF.png

執(zhí)行了invalidate方法后:timer--->target, runloop--->timer 之間的強引用被刪除缨叫。也就不會再有循環(huán)引用了椭符。(當repeats參數(shù)為NO時,timer 觸發(fā)后耻姥,這兩個強引用就自動被刪除了)销钝。

CA10278D-CD87-4C75-BC3C-280AE3403CE8.png

所以如果repeats為YES,并且沒有執(zhí)行invalidate方法時琐簇,形成了循環(huán)引用蒸健,這樣self就無法釋放,從而內(nèi)存泄漏。(有同學在self的dealloc方法中進行[timer invalidate]調(diào)用是無效果的鸽嫂,因為dealloc方法根本不會執(zhí)行纵装。)

2,self沒有強引用timer的情況
F165D713-F6FE-4DF1-A07A-48AF181C450B.png

執(zhí)行了invalidate方法后:timer--->target, runloop--->timer 之間的強引用被刪除据某。也就不會再有循環(huán)引用了橡娄。(當repeats參數(shù)為NO時,timer 觸發(fā)后癣籽,這兩個強引用就自動被刪除了)挽唉。

FA9FD847-7BC4-41EB-9355-F29FC09B931B.png

所以如果repeats為YES,并且沒有執(zhí)行invalidate方法時筷狼,雖然沒有循環(huán)引用瓶籽,但是runloop強引用timer,timer強引用self(target),由于(主線程中)runloop是程序運行期永久存在的埂材,所以timer無法釋放塑顺,self(target)也就無法釋放,從而內(nèi)存泄漏俏险。

系統(tǒng)方法中有一個方法不會導致self(target)無法釋放严拒。如下:

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block

該方法沒有參數(shù)targe,所以不會強引用self(target), 所以self(target)可以釋放竖独,但是如果沒有調(diào)用invalidate方法, 所創(chuàng)建的timer也是無法釋放的裤唠,所以依舊會內(nèi)存泄漏。

綜上所訴莹痢,當參數(shù)repeats為YES時种蘸,必須在不使用timer的時候調(diào)用invalidate方法刪除相關強引用,以免內(nèi)存泄漏竞膳。

避免循環(huán)引用的方式:

1航瞭,使用另一個對象,timer強引用newObjc坦辟,newObjc弱引用target沧奴。

github上已經(jīng)有了代碼:YYWeakProxy
對象引用圖:

E606D9DA-C690-4BB7-A00D-00EFE654E8E8.png

這樣timer就不再強引用self了,可以在self的dealloc中執(zhí)行invalidate方法釋放timer--->yyweakproxy, runloop----->timer的強引用.

原理:YYWeakProxy中weak屬性target长窄,并重寫forwardingTargetForSelector方法滔吠,直接返回_target.

- (id)forwardingTargetForSelector:(SEL)selector {
    return _target;
}
2纲菌,將target設置為類對象。

對象引用圖

B8EFCD0B-B320-40C4-BFB6-4F8210FCB831.png

雖然依舊有強引用:timer--->NSTimer類對象疮绷,但是由于類對象不需要回收翰舌,所以沒有內(nèi)存泄漏問題。
實現(xiàn)方式:

@interface NSTimer (BlocksSupport)
+(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                     block:(void(^)())block
                                   repeats:(BOOL)repeats;
@end
@implementation NSTimer (BlocksSupport)
+(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                     block:(void(^)())block
                                   repeats:(BOOL)repeats
{
return [self scheduledTimerWithTimeInterval:interval
                                      target:self
                                    selector:@selector(blockInvoke:)
                                    userInfo:[block copy]
                                     repeats:repeats];
}
+(void)blockInvoke:(NSTimer *)timer {
void (^block)() = timer.userinfo;
if(block) {
    block();
}
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末冬骚,一起剝皮案震驚了整個濱河市椅贱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌只冻,老刑警劉巖庇麦,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異喜德,居然都是意外死亡山橄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門舍悯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來航棱,“玉大人,你說我怎么就攤上這事萌衬∫迹” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵秕豫,是天一觀的道長朴艰。 經(jīng)常有香客問我,道長混移,這世上最難降的妖魔是什么祠墅? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮沫屡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撮珠。我一直安慰自己沮脖,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布芯急。 她就那樣靜靜地躺著勺届,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娶耍。 梳的紋絲不亂的頭發(fā)上免姿,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音榕酒,去河邊找鬼胚膊。 笑死故俐,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的紊婉。 我是一名探鬼主播药版,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喻犁!你這毒婦竟也來了槽片?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤肢础,失蹤者是張志新(化名)和其女友劉穎还栓,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體传轰,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡剩盒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了路召。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勃刨。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖股淡,靈堂內(nèi)的尸體忽然破棺而出身隐,到底是詐尸還是另有隱情,我是刑警寧澤唯灵,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布贾铝,位于F島的核電站,受9級特大地震影響埠帕,放射性物質(zhì)發(fā)生泄漏垢揩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一敛瓷、第九天 我趴在偏房一處隱蔽的房頂上張望叁巨。 院中可真熱鬧,春花似錦呐籽、人聲如沸锋勺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庶橱。三九已至,卻和暖如春贪惹,著一層夾襖步出監(jiān)牢的瞬間苏章,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留枫绅,地道東北人泉孩。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像撑瞧,于是被迫代替她去往敵國和親棵譬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一预伺、什么是NSRunLoop NSRunLoop是消息機制的處理模式 NSRunLoop的作用在于有事情做的時候使...
    呦釋原點閱讀 652評論 0 2
  • NSTimer是iOS最常用的定時器工具之一订咸,在使用的時候常常會遇到各種各樣的問題,最常見的是內(nèi)存泄漏酬诀,通常我們使...
    bomo閱讀 1,205評論 0 7
  • 創(chuàng)建NSTimer 創(chuàng)建NSTimer的常用方法是: + (NSTimer *)scheduledTimerWit...
    LanWor閱讀 1,370評論 0 2
  • 一脏嚷、什么是NSTimer 官方給出解釋是“A timer provides a way to perform a ...
    行走的菜譜閱讀 1,151評論 0 4
  • 數(shù)據(jù)內(nèi)容:在腫瘤測序數(shù)據(jù)中,發(fā)現(xiàn)血系變異與體細胞變異的疊加 數(shù)據(jù)來源:TCGA 數(shù)據(jù)理解: ①TCGA數(shù)據(jù)產(chǎn)生過程...
    union0402閱讀 784評論 0 0