iOS定時(shí)器帶來(lái)的內(nèi)存泄漏

本次代碼實(shí)踐源自一次面試.
Q:平時(shí)使用定時(shí)器NSTimer時(shí)如何釋放應(yīng)用它的target?
A:在viewDidDisappear中將調(diào)用invalid方法,在將timer置為nil.
但面試官想要的好像不是這個(gè)回答.

下面是我自己的答案的代碼實(shí)踐

- (void)viewDidLoad {
    [super viewDidLoad];

    self.timer = [NSTimer scheduledTimerWithTimeInterval:2
                                                  target:self
                                                selector:@selector(timeAction:)
                                                userInfo:nil
                                                 repeats:YES];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [self.timer invalidate];
    self.timer = nil;
}

上面代碼self應(yīng)用了timer,而timer頁(yè)應(yīng)用了self.這就形成了一個(gè)互相應(yīng)用,肯定會(huì)有內(nèi)存泄漏的.

我在dealloc方法打了斷點(diǎn),當(dāng)頁(yè)面消失后,的確會(huì)走到dealloc方法,說(shuō)明這樣做是可以釋放當(dāng)前self的.猜測(cè)應(yīng)該是viewDidDisappear中的操作斷開(kāi)了timer對(duì)self的應(yīng)用,從而內(nèi)存得以釋放.

下面是面試官給的思路

上面寫(xiě)的代碼導(dǎo)致內(nèi)存釋放不了的就是self和timer之間互相應(yīng)用了,想要self的釋放不受timer影響就必須斷開(kāi)二者的互相應(yīng)用.

關(guān)鍵點(diǎn)在于開(kāi)啟定時(shí)器時(shí)的target設(shè)置

我們定義一個(gè)中間件作為定時(shí)器的target,利用delegate回調(diào)定時(shí)器事件,由于delegate的弱應(yīng)用,就實(shí)現(xiàn)了timer對(duì)self的弱應(yīng)用.

//DetailViewController.m
#import "DetailViewController.h"
#import "Middleware.h"

@interface DetailViewController ()<MiddlewareDelegate>
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) Middleware *middleware;

@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.middleware = [[Middleware alloc] initWithDelegate:self];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:2
                                                  target:self.middleware
                                                selector:@selector(timeAction:)
                                                userInfo:nil
                                                 repeats:YES];
}

- (void)dealloc {

}

- (void)delegateTimerAction {
        NSLog(@"%f",CACurrentMediaTime());
}
@end
//Middleware.m
#import "Middleware.h"

@interface Middleware()

@property (nonatomic, weak) id<MiddlewareDelegate> delegate;
@end


@implementation Middleware

- (instancetype)initWithDelegate:(id<MiddlewareDelegate>)delegate {
    self = [super init];
    if (self) {
        self.delegate = delegate;
    }
    return self;
}

- (void)timeAction:(NSTimer *)timer {
    
    [self.delegate delegateTimerAction];
}

@end

當(dāng)我們推出當(dāng)前頁(yè)面時(shí),dealloc方法也會(huì)被調(diào)用,說(shuō)明當(dāng)前類(lèi)被釋放了.

從iOS10開(kāi)始,蘋(píng)果新增了3個(gè)創(chuàng)建定時(shí)器的方法用于避免循環(huán)引用
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval
                           repeats:(BOOL)repeats
                             block:(void (^)(NSTimer *timer))block;

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

- (instancetype)initWithFireDate:(NSDate *)date
                        interval:(NSTimeInterval)interval
                         repeats:(BOOL)repeats
                           block:(void (^)(NSTimer *timer))block;

這三個(gè)方法都將定時(shí)器要執(zhí)行的操作放在了block中,并且將當(dāng)前timer作為block的參數(shù)傳進(jìn)去了.

思考

對(duì)于第一種方法有個(gè)問(wèn)題,如果不是推出當(dāng)前頁(yè)面,而push到另一個(gè)頁(yè)面,每次回來(lái)都要銷(xiāo)毀創(chuàng)建創(chuàng)建銷(xiāo)毀.

對(duì)于平時(shí)使用的api,只是簡(jiǎn)單的會(huì)用,沒(méi)有深入去理解內(nèi)在的機(jī)制.以后要多去了解內(nèi)在機(jī)制、原理.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市解取,隨后出現(xiàn)的幾起案子西饵,更是在濱河造成了極大的恐慌谁榜,老刑警劉巖蔼水,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍启,死亡現(xiàn)場(chǎng)離奇詭異翁逞,居然都是意外死亡肋杖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)挖函,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)状植,“玉大人,你說(shuō)我怎么就攤上這事怨喘〗蚧” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵必怜,是天一觀的道長(zhǎng)肉拓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)梳庆,這世上最難降的妖魔是什么暖途? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任卑惜,我火速辦了婚禮,結(jié)果婚禮上驻售,老公的妹妹穿的比我還像新娘露久。我一直安慰自己,他們只是感情好欺栗,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布毫痕。 她就那樣靜靜地躺著,像睡著了一般迟几。 火紅的嫁衣襯著肌膚如雪消请。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天瘤旨,我揣著相機(jī)與錄音梯啤,去河邊找鬼。 笑死存哲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的七婴。 我是一名探鬼主播祟偷,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼打厘!你這毒婦竟也來(lái)了修肠?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤户盯,失蹤者是張志新(化名)和其女友劉穎嵌施,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體莽鸭,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吗伤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了硫眨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片足淆。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖礁阁,靈堂內(nèi)的尸體忽然破棺而出巧号,到底是詐尸還是另有隱情,我是刑警寧澤姥闭,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布丹鸿,位于F島的核電站,受9級(jí)特大地震影響棚品,放射性物質(zhì)發(fā)生泄漏靠欢。R本人自食惡果不足惜弥姻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掺涛。 院中可真熱鬧庭敦,春花似錦、人聲如沸薪缆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拣帽。三九已至疼电,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間减拭,已是汗流浹背蔽豺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拧粪,地道東北人修陡。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像可霎,于是被迫代替她去往敵國(guó)和親魄鸦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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