美文网首页
不需要手动释放的IOS定时器

不需要手动释放的IOS定时器

作者: 夏末秋刀鱼 | 来源:发表于2019-01-05 16:12 被阅读0次

    1.GCD
    优点:
    调用 dispatch_source_cancel(timer); 就会将 timer 对象销毁,唯一要考虑的就是 timer 的结束时机;即使你不主动释放timer, 也不会造成循环引用哦 O(∩_∩)O~,weaktarget释放时,定时器也会自己dispatch_source_cancel(),不需要像nstimer每次自己手动释放

    封装一个GCD定时器,原文:https://blog.csdn.net/zxw_xzr/article/details/68068368

    /**
     开启一个定时器
    
     @param target 定时器持有者
     @param timeInterval 执行间隔时间
     @param handler 重复执行事件
     */
    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);
                } else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (handler) handler(timer);
                    });
                }
            });
            // 启动定时器
            dispatch_resume(timer);
    }
    --------------------- 
    

    通过观察代码,我们可以发现GCD定时器实际上是使用了dispatch源(dispatch source),dispatch源监听系统内核对象并处理。dispatch类似生产者消费者模式,通过监听系统内核对象,在生产者生产数据后自动通知相应的dispatch队列执行,后者充当消费者。通过系统级调用,更加精准。

    补充其他定时器方法:
    NSTimer
    一般常用定时器为NSTimer
    1.只创建,需要手动加入RunLoop才会开始

    // 创建NSTimer对象
    NSTimer *timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    // 加入RunLoop中
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    

    2.创建自动加入到NSDefaultRunLoopMode

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action:) userInfo:nil repeats:YES];
    

    注意点:
    1.需要释放计时器,需要先销毁

    // 停止定时器
    [timer invalidate];
    timer = nil;
    

    2.UIScrollView 滑动时执行的是 UITrackingRunLoopMode,NSDefaultRunLoopMode被挂起,会导致定时器失效,等恢复为滑动结束时才恢复定时器。
    解决:

    //加入NSRunLoopCommonModes
    [[NSRunLoop mainRunLoop] addTimer:timer forMode: NSRunLoopCommonModes];
    

    3.NSTimer不是绝对准确的,如果此RunLoop正在执行一个连续性的运算,timer就会被延时出发。

    CADisplayLink
    (暂时没用过,暂且记下,主要是根据屏幕每次刷新调用)
    CADisplayLink对象是一个和屏幕刷新率同步的定时器对象。每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的 selector 就会被调用一次。
    从原理上可以看出,CADisplayLink适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染,或者做动画。

    使用方法:

    @property (nonatomic, strong) CADisplayLink *displayLink;
    
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];  
    
    // 每隔1帧调用一次
    self.displayLink.frameInterval = 1;  
    
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    

    释放方法

    [self.displayLink invalidate];  
    
    self.displayLink = nil;
    

    调用间隔时间为

    self.displayLink .frameInterval * self.displayLink.duration
    

    注意点:
    duration为只读属性,正常情况下IOS设备刷新为一秒钟60次,但是如果CPU过于繁忙,无法保证屏幕60次/秒的刷新率,就会导致跳过若干次调用回调方法的机会。所以CADisplayLink可以确保系统渲染每一帧的时候我们的方法都被调用,从而保证了动画的流畅性

    相关文章

      网友评论

          本文标题:不需要手动释放的IOS定时器

          本文链接:https://www.haomeiwen.com/subject/njbrrqtx.html