欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

定时器的几种实现方式

程序员文章站 2024-01-10 14:24:10
...

**一. ios端实现定时器的方式有以下三种方式
1).NSTimer
优点:使用方便,满足大多数需求,应用广泛
缺点:不太精准,受制于RunLoop,使用可能会造成内存泄露
使用:引导页,滑动页等等
2).GCD-Dispatch_source_t
优点:精度较高,系统自动触发,系统级别的源,不受制于RunLoop
缺点:时间事件可能被堵塞
使用:验证消息等待
3).CADisPlayLink
优点:刷新频率和设备屏幕同步,苹果手机屏幕60hz,每秒调用60次,依托设备触发事件,时间间隔最精准的定时器
缺点:CPU销毁过大,影响屏幕刷新,触发也会受影响,不能被继承
使用:和贝塞尔曲线+CAShapeLayer使用
二.具体实现
NSTimer

//创建方式1.默认添加到当前的runlooph中,默认defaultmodel 无需手动添加runloop中,会被其他事件打断
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerUpData) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
   
    //创建方式2
    //需要手动添加到runloop中,不会回不执行定时器
    _timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerUpData) userInfo:nil repeats:YES];
    //方式一默认model,会被打断
    [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSDefaultRunLoopMode];
    
    //方式二也会被打断
    [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:UITrackingRunLoopMode];
    
    //方式三 组合model不会内打断
    [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
    
    //销毁计时器
    [self.timer invalidate];
    
    
    //暂停计时器
    self.timer.fireDate = [NSDate distantFuture];
    //恢复计时器
    self.timer.fireDate = [NSDate distantPast];
    
    
    
    
    
    //子线程中使用
    __block NSTimer *disTimer;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        disTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerUpData) userInfo:nil repeats:YES];
       
        //启动线程
        [[NSRunLoop currentRunLoop] run];
    });

dispatch_soucrt

-(void)configDisPathSouorce{
    
    __block int timeOut = 30; //倒计时时间
    
    //创建异步队列,
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    //创建定时器
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    //开始时间
    dispatch_time_t startTime = dispatch_walltime(NULL,1.0*NSEC_PER_SEC);
    
   //间隔时间
    uint64_t interval = 1.0*NSEC_PER_SEC;
    //每秒执行
    dispatch_source_set_timer(timer,startTime, interval,0);
    
    
    
    dispatch_source_set_event_handler(timer, ^{
        
        //结束 关闭
        if (timeOut<=0) {
            
            dispatch_source_cancel(timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                //主线程 按钮怎么显示或者挑转等等
            });
            
            
        }else{
            
            int seconds = timeOut%60;
            NSString *timeStr = [NSString stringWithFormat:@"%.2d",seconds];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                //按钮显示 需求来
                NSLog(@"__%@",timeStr);
                
            });
            
            timeOut--;
        }
        
        
        
    });
    
    dispatch_resume(timer);
}

CADisPlayLink

-(void)configCADisplayLink{
    
    /*
     四个属性
     timestamp:获取上一次selector被执行的时间蔟,只读,需要selector执行一次之后才有值
     duration:获取当前设备屏幕刷新时间的间隔,只读属性,需要selector触发一次后有值
     
     
     
     
     */
    
    
    CADisplayLink *displayTime = [CADisplayLink displayLinkWithTarget:self selector:@selector(dispalychange)];
    
    //暂停 yes暂停 no不暂停
    displayTime.paused = YES;
    //触发间隔 弃用
    //displayTime.frameInterval = 2;
    //加入到runloop中
    [displayTime addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    //销毁
   // [displayTime invalidate];
    
}
-(void)dispalychange{
    
    
    
}
```**