Objective-C

iOS:三种定时器

2020-05-03  本文已影响0人  码小菜
风景

目录
一,NSTimer
二,CADisplayLink
三,dispatch_source_timer

一,NSTimer

1,基本使用

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0
                                            repeats:YES
                                              block:^(NSTimer * _Nonnull timer) {
        NSLog(@"timer running");
    }];
    [[NSRunLoop currentRunLoop] addTimer:timer
                                 forMode:NSDefaultRunLoopMode];
}

// 打印
07:21:30.266493+0800 Demo[10449:9624199] timer running
07:21:31.266367+0800 Demo[10449:9624199] timer running
07:21:32.266795+0800 Demo[10449:9624199] timer running
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 自动添加到runloop的NSDefaultRunLoopMode中
    [NSTimer scheduledTimerWithTimeInterval:1.0
                                    repeats:YES
                                      block:^(NSTimer * _Nonnull timer) {
        NSLog(@"timer running");
    }];
}

// 打印
07:24:10.249589+0800 Demo[10584:9626453] timer running
07:24:11.250144+0800 Demo[10584:9626453] timer running
07:24:12.250318+0800 Demo[10584:9626453] timer running
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"begin");
    NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:3.0]
                                              interval:1.0
                                               repeats:YES
                                                 block:^(NSTimer * _Nonnull timer) {
        NSLog(@"timer running");
    }];
    [[NSRunLoop currentRunLoop] addTimer:timer
                                 forMode:NSDefaultRunLoopMode];
}

// 打印
07:32:16.943407+0800 Demo[10738:9632602] begin
07:32:19.944573+0800 Demo[10738:9632602] timer running
07:32:20.944960+0800 Demo[10738:9632602] timer running
07:32:21.944652+0800 Demo[10738:9632602] timer running

2,解决循环引用

/**
 self强引用timer,timer强引用proxy,proxy弱引用self
 */

// YJProxy.h
@interface YJProxy : NSObject
+ (instancetype)proxyWithTarget:(id)target;
@end

// YJProxy.m
@interface YJProxy ()
@property (nonatomic, weak) id target; // 弱引用
@end

@implementation YJProxy
+ (instancetype)proxyWithTarget:(id)target {
    YJProxy *proxy = [[YJProxy alloc] init];
    proxy.target = target;
    return proxy;
}
- (id)forwardingTargetForSelector:(SEL)aSelector { // 消息转发
    return self.target;
}
@end

// ViewController
@interface ViewController ()
@property (nonatomic, strong) NSTimer *timer;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                  target:[YJProxy proxyWithTarget:self]
                                                selector:@selector(timerTask)
                                                userInfo:nil
                                                 repeats:YES];
}
- (void)timerTask {
    NSLog(@"%s", __func__);
}
- (void)dealloc {
    NSLog(@"%s", __func__);
    [self.timer invalidate];
}
@end

// 打印
07:56:14.897620+0800 Demo[11187:9646035] -[ViewController timerTask]
07:56:15.897446+0800 Demo[11187:9646035] -[ViewController timerTask]
07:56:16.898022+0800 Demo[11187:9646035] -[ViewController timerTask]
07:56:17.860300+0800 Demo[11187:9646035] -[ViewController dealloc]

3,NSProxy

@interface YJProxy : NSProxy
+ (instancetype)proxyWithTarget:(id)target;
@end

@interface YJProxy ()
@property (nonatomic, weak) id target;
@end

@implementation YJProxy
+ (instancetype)proxyWithTarget:(id)target {
    // NSProxy没有init方法
    YJProxy *proxy = [YJProxy alloc];
    proxy.target = target;
    return proxy;
}
// 消息转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}
@end

1>它跟NSObject是同一级别的

2>它专用于消息转发

3>用它做代理对象效率更高,因为它是直接执行消息转发的,而NSObject需要先执行消息发送和动态方法解析

二,CADisplayLink

1,使用

@interface ViewController ()
@property (nonatomic, strong) CADisplayLink *link;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.link = [CADisplayLink displayLinkWithTarget:[YJProxy proxyWithTarget:self]
                                            selector:@selector(linkTask)];
    // 设置每秒执行1次
    self.link.preferredFramesPerSecond = 1;
    [self.link addToRunLoop:[NSRunLoop currentRunLoop]
                    forMode:NSDefaultRunLoopMode];
}
- (void)linkTask {
    NSLog(@"%s", __func__);
    // 下一次执行的时间 - 当前时间
    NSLog(@"%f", self.link.targetTimestamp - self.link.timestamp);
    // 两帧之间的时间间隔
    NSLog(@"%f", self.link.duration);
}
- (void)dealloc {
    NSLog(@"%s", __func__);
    [self.link invalidate];
}
@end

// 打印
13:26:37.176374+0800 Demo[15813:9765865] -[ViewController linkTask]
13:26:37.176581+0800 Demo[15813:9765865] 1.000000
13:26:37.176682+0800 Demo[15813:9765865] 0.016667
13:26:38.172891+0800 Demo[15813:9765865] -[ViewController linkTask]
13:26:38.173096+0800 Demo[15813:9765865] 1.000000
13:26:38.173237+0800 Demo[15813:9765865] 0.016667
13:26:39.173083+0800 Demo[15813:9765865] -[ViewController linkTask]
13:26:39.173282+0800 Demo[15813:9765865] 1.000000
13:26:39.173442+0800 Demo[15813:9765865] 0.016667
13:26:39.207185+0800 Demo[15813:9765865] -[ViewController dealloc]

2,说明

三,dispatch_source_timer

1,使用

@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t timer;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 创建定时器并设置执行任务的队列
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    // 每1秒执行一次任务并允许有1秒的误差
    dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 1.0 * NSEC_PER_SEC);
    
    // 定时器任务
    dispatch_source_set_event_handler(self.timer, ^{
        NSLog(@"timer running---%@", [NSThread currentThread]);
    });
    
    // 定时器被取消的回调
    dispatch_source_set_cancel_handler(self.timer, ^{
        NSLog(@"timer cancelled---%@", [NSThread currentThread]);
    });
    
    // 启动定时器
    dispatch_resume(self.timer);
}
- (void)dealloc {
    NSLog(@"%s", __func__);
    // 取消定时器
    dispatch_source_cancel(self.timer);
}
@end

// 打印
15:15:24.073246+0800 Demo[17534:9809826] timer running---<NSThread: 0x6000035f2bc0>{number = 8, name = (null)}
15:15:25.073340+0800 Demo[17534:9809827] timer running---<NSThread: 0x6000035c5000>{number = 8, name = (null)}
15:15:26.155698+0800 Demo[17534:9809827] timer running---<NSThread: 0x6000035c5000>{number = 6, name = (null)}
15:15:27.247158+0800 Demo[17534:9809775] -[ViewController dealloc]
15:15:27.247717+0800 Demo[17534:9809827] timer cancelled---<NSThread: 0x6000035c5000>{number = 5, name = (null)}

2,说明

上一篇 下一篇

猜你喜欢

热点阅读