使用NSTimer可能會(huì)碰到循環(huán)引用的問題。特別是當(dāng)類具有NSTimer類型的成員變量,并且需要反復(fù)執(zhí)行計(jì)時(shí)任務(wù)時(shí)。例如
_timer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(startCounting) userInfo:nil
repeats:YES];
類有一個(gè)成員變量_timer
,給_timer
設(shè)置的target
為這個(gè)類本身换可。這樣類保留_timer
,_timer
又保留了這個(gè)類厦幅,就會(huì)出現(xiàn)循環(huán)引用的問題沾鳄,最后導(dǎo)致類無法正確釋放。
解決這個(gè)問題的方式也很簡(jiǎn)單确憨,當(dāng)類的使用者能夠確定不需要使用這個(gè)計(jì)時(shí)器時(shí)译荞,就調(diào)用
[_timer invalidate];
_timer = nil;
這樣就打破了保留環(huán),類也可以正確釋放休弃。但是吞歼,這種依賴于開發(fā)者手動(dòng)調(diào)用方法,才能讓內(nèi)存正確釋放的方式不是一個(gè)非常好的處理方式塔猾。所以需要另外一種解決方案篙骡。如下所示:
@interface NSTimer (JQUsingBlock)
+ (NSTimer *)jq_scheduledTimerWithTimeInterval:(NSTimeInterval)ti
block:(void(^)())block
repeats:(BOOL)repeats;
@end
@implementation NSTimer (JQUsingBlock)
+ (NSTimer *)jq_scheduledTimerWithTimeInterval:(NSTimeInterval)ti
block:(void(^)())block
repeats:(BOOL)repeats{
return [self scheduledTimerWithTimeInterval:ti
target:self
selector:@selector(jq_blockInvoke:)
userInfo:[block copy]
repeats:repeats];
}
+ (void)jq_blockInvoke:(NSTimer *)timer{
void(^block)() = timer.userInfo;
if (block) {
block();
}
}
@end
定義一個(gè)NSTimer
的類別,在類別中定義一個(gè)類方法。類方法有一個(gè)類型為塊的參數(shù)(定義的塊位于棧上糯俗,為了防止塊被釋放慎皱,需要調(diào)用copy
方法,將塊移到堆上)叶骨。使用這個(gè)類別的方式如下:
__weak ViewController *weakSelf = self;
_timer = [NSTimer jq_scheduledTimerWithTimeInterval:5.0
block:^{
__strong ViewController *strongSelf = weakSelf;
[strongSelf startCounting];
}
repeats:YES];
使用這種方案就可以防止NSTimer
對(duì)類的保留,從而打破了循環(huán)引用的產(chǎn)生祈匙。__strong ViewController *strongSelf = weakSelf
主要是為了防止執(zhí)行塊的代碼時(shí)忽刽,類被釋放了。在類的dealloc
方法中夺欲,記得調(diào)用[_timer invalidate]
跪帝。