一: 分类封装
import UIKit
@objc public extension Timer{
/// 分类方法
static func scheduled(_ Interval: TimeInterval = 60, repeats: Bool = true, action: @escaping((Timer) -> Void)) -> Timer {
return scheduledTimer(timeInterval: Interval, target: self, selector: #selector(handleInvoke(_:)), userInfo: action, repeats: repeats)
}
private static func handleInvoke(_ timer: Timer) {
if let action = timer.userInfo as? ((Timer) -> Void) {
action(timer)
}
}
func activate() {
// 继续:触发时间设置在现在/获取,这样定时器自动进入马上进入工作状态.
self.fireDate = .distantPast
}
func pause() {
// 暂停:触发时间设置在未来,既很久之后,这样定时器自动进入等待触发的状态.
self.fireDate = .distantFuture
}
func destroy() {
self.invalidate()
}
static func createGCDTimer(_ interval: TimeInterval = 60, repeats: Bool = true, action: @escaping(() -> Void)) -> DispatchSourceTimer {
let codeTimer = DispatchSource.makeTimerSource(flags: .init(rawValue: 0), queue: DispatchQueue.global())
codeTimer.schedule(deadline: .now(), repeating: .milliseconds(1000))
codeTimer.setEventHandler {
if repeats == false {
codeTimer.cancel()
}
DispatchQueue.main.async(execute: action)
}
codeTimer.resume()
return codeTimer;
}
static func destoryGCDTimer(_ timer: DispatchSourceTimer?) {
timer?.cancel()
}
}
public extension DispatchSourceTimer{
static func create(_ interval: TimeInterval = 60, repeats: Bool = true, action: @escaping(() -> Void)) -> DispatchSourceTimer {
let codeTimer = DispatchSource.makeTimerSource(flags: .init(rawValue: 0), queue: DispatchQueue.global())
codeTimer.schedule(deadline: .now(), repeating: .milliseconds(1000))
codeTimer.setEventHandler {
if repeats == false {
codeTimer.cancel()
}
DispatchQueue.main.async(execute: action)
}
codeTimer.resume()
return codeTimer
}
}
OC
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSTimer (Helper)
+ (NSTimer *)scheduledTimer:(NSTimeInterval)interval
block:(void(^)(NSTimer *timer))block
repeats:(BOOL)repeats;
///GCD定时器(秒)
+ (dispatch_source_t)createGCDTimer:(NSTimeInterval)interval
repeats:(BOOL)repeats
block:(void (^)(void))block;
+(void)destoryGCDTimer:(dispatch_source_t)timer;
///激活/启动
- (void)activate;
///暂停
- (void)pause;
//销毁
- (void)destroy;
@end
NS_ASSUME_NONNULL_END
#import "NSTimer+Helper.h"
@implementation NSTimer (Helper)
+ (NSTimer *)scheduledTimer:(NSTimeInterval)interval
block:(void(^)(NSTimer *timer))block
repeats:(BOOL)repeats{
return [self scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(handleInvoke:)
userInfo:[block copy]
repeats:repeats];
}
+ (void)handleInvoke:(NSTimer *)timer {
void(^block)(NSTimer *timer) = timer.userInfo;
if(block) {
block(timer);
}
}
+ (dispatch_source_t)createGCDTimer:(NSTimeInterval)interval
repeats:(BOOL)repeats
block:(void (^)(void))block{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
dispatch_source_set_timer(timer,dispatch_walltime(NULL, 0), interval * NSEC_PER_SEC, 0); //执行间隔
dispatch_source_set_event_handler(timer, ^{
if (!repeats) {
dispatch_source_cancel(timer);
}
dispatch_async(dispatch_get_main_queue(), block);
});
dispatch_resume(timer); // 启动定时器
return timer;
}
+(void)destoryGCDTimer:(dispatch_source_t)timer{
if (timer) {
dispatch_source_cancel(timer);
}
}
- (void)activate{
self.fireDate = NSDate.distantPast;
// self.fireDate = NSDate.date;
}
- (void)pause{
self.fireDate = NSDate.distantFuture;
}
- (void)destroy{
[self invalidate];
// self == nil;
}
@end
二.工具类封装
void dispatchTimer(id target, double timeInterval,void (^handler)(dispatch_source_t timer)){
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0, 0, queue);
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), (uint64_t)(timeInterval *NSEC_PER_SEC), 0);
// 设置回调
__weak __typeof(target) weaktarget = target;
dispatch_source_set_event_handler(timer, ^{
if (!weaktarget) {
dispatch_source_cancel(timer);
NSLog(@"dispatch_source_cancel!!!");
} else {
dispatch_async(dispatch_get_main_queue(), ^{
if (handler) handler(timer);
});
}
});
// 启动定时器
dispatch_resume(timer);
}
示例:
@property (nonatomic, strong) NSTimer *timer;
-(void)dealloc{
[_timer destroy];
}
- (void)viewDidLoad {
[super viewDidLoad];
__block NSInteger i = 0;
_timer = [NSTimer scheduledTimer:1 block:^(NSTimer *timer) {
i++;
DDLog(@"__%@",@(i));
} repeats:YES];
[NSTimer createGCDTimer:1 repeats:true block:^{
i++;
DDLog(@"%@",@(i));
}];
DDLog(@"___%@",@(i));
}
须知:
1. 调用 NSTimer 会对调用的对象 retain
2. NSTimer 必须加入 NSRunloop 中才能正确执行
3. NSTimer 并不是一个实时的系统(不准确)
4. NSRunLoopCommonModes 这是一个伪模式,是 run loop mode 的集合,此模式意味着在 Common Modes 中包含的所有模式下都可以处理。
在 Cocoa 应用程序中,默认情况下 Common Modes 包含 default modes, modal modes, event Tracking modes.
可使用 CFRunLoopAddCommonMode 方法想 Common Modes 中添加自定义 modes。