NSTimer不釋放問(wèn)題

相信iOS開(kāi)發(fā)過(guò)程中,肯定大多數(shù)人都知道Timer的釋放不掉問(wèn)題,但是否認(rèn)真考慮過(guò)其中釋放不掉的原因?

self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerRun:) userInfo:nil repeats:YES];

NSTimer不釋放原因


其中考慮較多的一個(gè)版本是:controller與Timer循環(huán)引用,導(dǎo)致彼此不能釋放,但真正原因真是這樣嗎?

驗(yàn)證方式:

1.把timer寫(xiě)為局部變量,避免controller強(qiáng)引用timer
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerRun:) userInfo:nil repeats:YES];

然而,并不能釋放。

2.我們來(lái)看看引用情況

打開(kāi)xcode的Debug Memory Graph工具,在這里

Debug Memory Graph

能看到內(nèi)存引用情況
內(nèi)存引用情況

驗(yàn)證結(jié)果:只有timer單向的指向target,target并未指向timer。而timer的不釋放原因在于runloop的強(qiáng)引用,見(jiàn)官方文檔:
image.png

錯(cuò)誤解決辦法


1.dealloc中調(diào)用invalidate
- (void)dealloc {
       if(_timer) {
            [_timer invalidate];
       }
}

這是不行的!
如果_timer的target是self,會(huì)對(duì)self進(jìn)行強(qiáng)引用(即使傳入weakSelf也是不行的),導(dǎo)致self不能釋放,也就不會(huì)走到dealloc方法里。

2.viewWillDisappear中invalidate

這種方式是可以釋放掉的。
但如果我只是想在離開(kāi)此頁(yè)時(shí)要釋放,進(jìn)入下一頁(yè)時(shí)不要釋放,場(chǎng)景就不適用了。

正確解決辦法


添加一個(gè)NSTimer類的擴(kuò)展,把target指給[NSTimer class],事件由加方法接收,然后把事件通過(guò)block傳遞出來(lái)。

@interface NSTimer (block)

+ (instancetype)repeatWithInterval:(NSTimeInterval)interval block:(void(^)(NSTimer *timer))block;

@end

@implementation NSTimer (block)

+ (instancetype)repeatWithInterval:(NSTimeInterval)interval block:(void(^)(NSTimer *timer))block {
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(trigger:) userInfo:[block copy] repeats:YES];
    return timer;
}

+ (void)trigger:(NSTimer *)timer {
    void(^block)(NSTimer *timer) = [timer userInfo];
    if (block) {
        block(timer);
    }
}

@end

巧妙點(diǎn)在于把block作為timer的userInfo傳遞進(jìn)入trigger:方法,避免了在本類中再添加個(gè)參數(shù)記錄block。

使用示例
@interface CAAnimationViewController () 

@property (nonatomic, weak)   NSTimer *timer;

@end

@implementation CAAnimationViewController

- (void)viewDidLoad {
    kWeakSelf
    self.timer = [NSTimer repeatWithInterval:1 block:^(NSTimer *timer) {
        //收到timer回調(diào)
        [weakSelf dosomething];
    }];
}

- (void)dealloc {
    [_timer invalidate];
}

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

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

  • 之前要做一個(gè)發(fā)送短信驗(yàn)證碼的倒計(jì)時(shí)功能,打算用NSTimer來(lái)實(shí)現(xiàn),做的過(guò)程中發(fā)現(xiàn)坑還是有不少的。 基本使用 NS...
    WeiHing閱讀 4,469評(píng)論 1 8
  • 面試中,經(jīng)常會(huì)問(wèn)道 NSTimer 循環(huán)引用的問(wèn)題。閑話少敘。下面來(lái)講講 NSTimer 為什么會(huì)造成循環(huán)引用? ...
    人話博客閱讀 1,518評(píng)論 0 53
  • 創(chuàng)建NSTimer 創(chuàng)建NSTimer的常用方法是: + (NSTimer *)scheduledTimerWit...
    LanWor閱讀 1,488評(píng)論 0 2
  • 用戶編號(hào):1339494166
    飛翔的蝸牛_曲晶閱讀 200評(píng)論 0 0
  • 嘴賤的人沒(méi)有福氣。開(kāi)口說(shuō)不得善語(yǔ)的人內(nèi)心污穢。福氣都被嚇跑了。與人交流亦多是爭(zhēng)吵。
    太陽(yáng)花哦閱讀 408評(píng)論 0 1

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