接上篇的講解净赴,項目實戰(zhàn)定義了一個不需要手動釋放的NSTimer
實現(xiàn)思路:了解定時器的同學肯定知道嗡善,定時器會保留其目標對象笋熬,目標對象又同時持有了定時器蚂会。只有在定時器失效時釋放目標對象转捕,但程序中反復執(zhí)行定時任務(wù)容易出現(xiàn)內(nèi)存泄露的問題作岖。首先自定義了一個target,在target里定義了一個weak修飾的timer五芝,target里還定義了timer所應(yīng)執(zhí)行任務(wù)的方法痘儡,并將此方法封裝成塊來調(diào)用的。然后寫了一個NSTimer的分類枢步,將target指向我們自定義的target沉删,然后重寫了部分定時器相關(guān)的方法
//NSTimer+AutoIncalidate.h
#import <Foundation/Foundation.h>
typedef void(^ZDTimeTargetBlock)(NSTimer *timer);
@interface ZDTimerTarget : NSObject
@end
@interface NSTimer (AutoIncalidate)
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti
block:(ZDTimeTargetBlock)block
userInfo:(id)userInfo
repeats:(BOOL)yesOrNo
existObject:(id)existObj;
- (void)pauseTimer;
- (void)resumeTimer;
- (void)resumeTimerAfterTimeInterval:(NSTimeInterval)interval;
@end
#import "NSTimer+AutoIncalidate.h"
@interface ZDTimerTarget ()
@property (nonatomic ,weak)NSTimer *timer; //注意是weak
@property (nonatomic,copy) ZDTimeTargetBlock block;
@property (nonatomic,weak) id existObj; //注意是weak
@end
@implementation ZDTimerTarget
- (id)initWithTimerTargetBlock:(ZDTimeTargetBlock)block timer:(NSTimer *)timer existObj:(id)existObj {
if (self = [super init]) {
_block = block;
_timer = timer;
_existObj = existObj;
}
return self;
}
- (void)incocaiton {
if (_existObj) {
if ((_block)) {
_block(_timer);
}
}else {
[_timer invalidate];
_timer = nil;
}
}
@end
@implementation NSTimer (AutoIncalidate)
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)intervval
block:(ZDTimeTargetBlock)block
userInfo:(id)userInfo
repeats:(BOOL)yesOrNo
existObject:(id)existObj
{
ZDTimerTarget *target = [[ZDTimerTarget alloc] initWithTimerTargetBlock:block timer:nil existObj:existObj];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:intervval target:target selector:@selector(incocaiton) userInfo:userInfo repeats:yesOrNo];
target.timer = timer;
return timer;
}
-(void)pauseTimer
{
if (![self isValid]) {
return ;
}
[self setFireDate:[NSDate distantFuture]];
}
-(void)resumeTimer
{
if (![self isValid]) {
return ;
}
[self setFireDate:[NSDate date]];
}
- (void)resumeTimerAfterTimeInterval:(NSTimeInterval)interval
{
if (![self isValid]) {
return ;
}
[self setFireDate:[NSDate dateWithTimeIntervalSinceNow:interval]];
}
@end