系統提供的NSTimer類,很多的時候內存的釋放是一個大問題,尤其是repeat方式的,通過調試發現它是基本上不釋放的。我個人就考慮用GCD來實現一套定時器的功能。詳細見下面的code:
//
// DispatchTimer.h
// WYJDemoSets
//
// Created by wuyj on 16/2/18.
// Copyright © 2016年 wuyj. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol DispatchTimerDelegate <NSObject>
- (void)dispatchTimerTask;
@end
typedef void (^DispatchTimerBlock)(void);
/*
採用GCD實現timer,這個實現不會出現timer不釋放的問題;
*/
@interface DispatchTimer :NSObject
+ (DispatchTimer *)sharedDispatchTimer;
// 採用代理的方式,建議採用這種方式
- (void)createDispatchTimerInterval:(NSUInteger)interval delegate:(id <DispatchTimerDelegate>)delegate repeats:(BOOL)yesOrNo;
/* !!!!!! 採用block的方式,一定要注意block retain self的問題
類似這樣使用:
__weak CycleScrollView *wself = self;
[[DispatchTimer sharedDispatchTimer] createDispatchTimerInterval:_interval block:^{
CycleScrollView *sself = wself;
[sself autoJumpPage];
} repeats:YES];
*/
- (void)createDispatchTimerInterval:(NSUInteger)interval block:(DispatchTimerBlock)timerBlock repeats:(BOOL)yesOrNo;
// 停止循環執行的timer
- (void)invalidate;
@end
//
// DispatchTimer.m
// WYJDemoSets
//
// Created by wuyj on 16/2/18.
// Copyright © 2016年 wuyj. All rights reserved.
//
#import "DispatchTimer.h"
@interface DispatchTimer ()
@property (nonatomic,strong) dispatch_source_t timer;
@property (nonatomic,weak) id<DispatchTimerDelegate> delegate;
@end
@implementation DispatchTimer
+ (DispatchTimer *)sharedDispatchTimer {
staticDispatchTimer *obj = nil;
staticdispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
obj = [[selfalloc] init];
});
return obj;
}
- (void)dealloc {
[selfinvalidate];
}
- (void)createDispatchTimerInterval:(NSUInteger)interval delegate:(id <DispatchTimerDelegate>)delegate repeats:(BOOL)yesOrNo {
self.delegate = delegate;
if (yesOrNo) {
// 獲得隊列
dispatch_queue_t queue =dispatch_get_main_queue();
self.timer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0, 0, queue);
dispatch_time_t start =dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval *NSEC_PER_SEC));
uint64_t dur = (uint64_t)(interval *NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, dur,0);
// 設置回調
__weakDispatchTimer *wTimer = self;
dispatch_source_set_event_handler(self.timer,^{
//執行事件
DispatchTimer *sTimer = wTimer;
if (sTimer.delegate && [sTimer.delegaterespondsToSelector:@selector(dispatchTimerTask)]) {
[sTimer.delegatedispatchTimerTask];
}
});
// 啓動定時器
dispatch_resume(self.timer);
} else {
dispatch_time_t popTime =dispatch_time(DISPATCH_TIME_NOW, interval *NSEC_PER_SEC);
// 設置回調
__weakDispatchTimer *wTimer = self;
dispatch_after(popTime,dispatch_get_main_queue(), ^(void){
//執行事件
DispatchTimer *sTimer = wTimer;
if (sTimer.delegate && [sTimer.delegaterespondsToSelector:@selector(dispatchTimerTask)]) {
[sTimer.delegatedispatchTimerTask];
}
});
}
}
- (void)createDispatchTimerInterval:(NSUInteger)interval block:(DispatchTimerBlock)timerBlock repeats:(BOOL)yesOrNo {
if (yesOrNo) {
// 獲得隊列
dispatch_queue_t queue =dispatch_get_main_queue();
self.timer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0, 0, queue);
dispatch_time_t start =dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 *NSEC_PER_SEC));
uint64_t dur = (uint64_t)(interval *NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, dur,0);
// 設置回調
dispatch_source_set_event_handler(self.timer, timerBlock);
// 啓動定時器
dispatch_resume(self.timer);
} else {
dispatch_time_t popTime =dispatch_time(DISPATCH_TIME_NOW, interval *NSEC_PER_SEC);
dispatch_after(popTime,dispatch_get_main_queue(), timerBlock);
}
}
- (void)invalidate {
if (self.timer) {
dispatch_cancel(self.timer);
self.timer =nil;
}
}
@end