zoukankan      html  css  js  c++  java
  • Object-C定时器,封装GCD定时器的必要性!!! (一)

    实际项目开发中经常会遇到延迟某件任务的执行,或者让某件任务周期性的执行。然后也会在某些时候需要取消掉之前延迟执行的任务。

    iOS中延迟操作有三种解决方案:

    1、NSObject的方法:(对象方法)

    - (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;

    2、使用NSTimer的方法:

    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

    //需要手动添加到运行循环

    ------------------------------------------------------------------------------

    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

    //创建后会默认添加到NSDefaultRunLoopMode中,这个方法创建的定时器不会自动销毁,需要手动销毁,会被self强引用着,不特殊处理就会产生强引用循环,造成内存泄露. 一定不要使用这个方法,请使用下面的方法替代这个方法.

    ------------------------------------------------------------------------------

    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

    //创建后会默认添加到NSDefaultRunLoopMode中,添加到block中,系统回自己处理(不会强引用),系统会调用dealloc方法我们在此处销毁timer即可

    ------------------------------------------------------------------------------

     

     

    模式:以下两种模式同一时刻只能是一种模式

    NSDefaultRunLoopMode(默认模式)

    UITrackingRunLoopMode(如果控制器的view上面有滚动视图,但手指拖拽滚动视图的时候,就会进入该模式.一般不会将定时器加入到这个模式中,如果想在滚动视图的时候,定时器同样起效一般会加入到下面的模式) 

    ---------------------------------------------------------------------------------------

    NSRunLoopCommonModes:上面两个模式都能运行

     

     

    3、使用GCD的方法:

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

         //延迟执行的代码 

      

    });

     

    一般情况下,我们选择使用GCD的dispatch_after。

    因为如果不用GCD,需要注意以下三个细节:

    1.必须保证有一个活跃的runloop。

    当一个应用启动时,系统会开启一个主线程,并且把主线程跑起来,并且主线程的runloop是不会停止的。所以,当这两个方法在主线程可以被正常调用。但实际编程中大部分逻辑处理是放在子线程中执行的。而子线程的runloop是默认关闭的。如果不手动激活runloop,performSelector和scheduledTimerWithTimeInterval的调用将是无效的。

    2.NSTimer、performSelector的创建与撤销必须在同一个线程操作。

    3.内存有潜在泄露的风险 

    4.NSTimer相对于Dispatch定时器来说不准时.

    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

    //当然使用这个方法,不会产生强引用循环(系统已经帮我们处理了),我们只需要在对应的dealloc方法中销毁定时器就OK了

    但是dispatch_after有个致命的弱点:dispatch_after一旦执行后,就不能撤销了。

    其实GCD也有timer的功能。

    // 1.获得队列

     dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

      //dispatch_queue_t queue = dispatch_get_main_queue();

     

     // 2.创建一个定时器(dispatch_source_t本质还是个OC对象

     self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

     

     // 3.设置timer执行的事件

    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW,1.0 * NSEC_PER_SEC);//1.0秒之后开始执行

     uint64_t interval = (uint64_t)(2.0 * NSEC_PER_SEC);//每隔2.0秒执行一次

     dispatch_source_set_timer(self.timer, start, interval, 0);

     

     //4. 设置回调

     dispatch_source_set_event_handler(self.timer, ^{

          // 取消timer 或者做其他事情

          dispatch_cancel(self.timer);

          self.timer = nil;

     });

     

     //5.启动定时器/激活timer

     dispatch_resume(self.timer);

     

    这样我们就规避了NSTimer的三个缺陷。

    我靠... 这也太复杂了!!! 而且还没有repeats选项

    我们能不能像NSTimer那样使用呢?答案:当然有了!!!

    没错! 我们将重复的代码封装起来,开放几个供外界调用的参数!

    有了思路写代码就很简单了!

     

     

    更多内容--> 博客导航 每周一篇哟!!!

     

     

    有任何关于iOS开发的问题!欢迎下方留言!!!或者邮件lieryangios@126.com 虽然我不一定能够解答出来,但是我会请教iOS开发高手!!!解答您的问题!!!

     

     

     

    详细设计请看下一篇: Object-C定时器,封装GCD定时器的必要性!!! (二)

     

     

  • 相关阅读:
    547. Friend Circles
    399. Evaluate Division
    684. Redundant Connection
    327. Count of Range Sum
    LeetCode 130 被围绕的区域
    LeetCode 696 计数二进制子串
    LeetCode 116 填充每个节点的下一个右侧节点
    LeetCode 101 对称二叉树
    LeetCode 111 二叉树最小深度
    LeetCode 59 螺旋矩阵II
  • 原文地址:https://www.cnblogs.com/CoderEYLee/p/Object-C-0004.html
Copyright © 2011-2022 走看看