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

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

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

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
span.s2 { color: #bb2ca2 }
span.s3 { color: #703daa }

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

2、使用NSTimer的方法:

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
span.s2 { color: #703daa }
span.s3 { color: #bb2ca2 }
span.s4 { color: #78492a }
span.s5 { color: #272ad8 }

+ (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即可

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

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
span.s2 { color: #703daa }
span.s3 { color: #bb2ca2 }

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

NSDefaultRunLoopMode(默认模式)

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

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

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #008400 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #008400; min-height: 24.0px }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px "PingFang SC"; color: #008400 }
span.s1 { }
span.s2 { font: 20.0px "PingFang SC" }
span.s3 { font: 20.0px Menlo }

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

3、使用GCD的方法:

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #703daa }
span.s1 { }
span.s2 { color: #703daa }
span.s3 { color: #000000 }
span.Apple-tab-span { white-space: pre }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #3e1e81 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #000000; min-height: 24.0px }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #000000 }
span.s1 { }
span.s2 { color: #000000 }
span.s3 { color: #78492a }
span.s4 { color: #703daa }
span.s5 { color: #272ad8 }

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的功能。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #008400 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #008400; min-height: 24.0px }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px "PingFang SC"; color: #008400 }
span.s1 { }
span.s2 { font: 20.0px "PingFang SC" }
span.s3 { font: 20.0px Menlo }

// 1.获得队列

, );

//dispatch_queue_t queue = dispatch_get_main_queue();

// 2.创建一个定时器(dispatch_source_t本质韩式哥OC对象

, , 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秒执行一次

);

//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定时器的必要性!!! (二)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #703daa }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #703daa }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; color: #d12f1b }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo; min-height: 24.0px }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { color: #78492a }
span.s2 { }
span.s3 { color: #bb2ca2 }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }
span.s2 { color: #703daa }
span.s3 { color: #bb2ca2 }
span.s4 { color: #78492a }
span.s5 { color: #272ad8 }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Menlo }
span.s1 { }

Object-C定时器,封装GCD定时器的必要性!!! (一)的更多相关文章

  1. Object-C定时器,封装GCD定时器的必要性!!! (二)

    上一篇:Object-C定时器,封装GCD定时器的必要性!!! (一) 上一篇认识了Object-C中的几种定时器,这一篇将Dispatch定时器(GCD定时器)封装起来. p.p1 { margin ...

  2. GCD定时器

    // // ViewController.m // GCD 定时器 // // #import "ViewController.h" NSInteger count = ; @in ...

  3. IOS GCD定时器

    提到定时器,NStimer肯定是我们最为熟悉的. 但是NStimer有着很大的缺点,并不准确. 通俗点说,就是它该做他的事了,但是由于其他事件的影响,Nstimer会放弃他应该做的. 而GCD定时器, ...

  4. runloop 和 CFRunLoop - 定时器 - NSTimer 和 GCD定时器

    1. 2. #import "ViewController.h" @interface ViewController () @property (nonatomic, strong ...

  5. 关于普通定时器与高级定时器的 PWM输出的初始化的区别

    不管是普通定时器还是高级定时器,你用哪个通道,就在程序里用OC多少.比如CH3对应OC3 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  TIM_ ...

  6. [ZigBee] 6、ZigBee基础实验——定时器3和定时器4(8 位定时器)

    上一节讲了16位定时器1,本节讲8位定时器3和定时器4! 1.综述 Timer 3 and Timer 4 are two 8-bit timers(8位定时器). Each timer has tw ...

  7. 14.TCP的坚持定时器和保活定时器

    一.坚持定时器   1.坚持定时器的由来         TCP通过让接收方指明希望从发送方接受的窗口大小来进行流量控制.设置窗口大小为0可以组织发送方传送数据,直至窗口变为非0为止.         ...

  8. TCP的定时器系列 — 保活定时器

    主要内容:保活定时器的实现,TCP_USER_TIMEOUT选项的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 原理 HTTP有Keepaliv ...

  9. TCP的定时器系列 — SYNACK定时器

    主要内容:SYNACK定时器的实现,TCP_DEFER_ACCPET选项的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 在上一篇博客中,已经连带 ...

随机推荐

  1. mybatis进阶--一对一查询

    所谓的一对一查询,就是说我们在查询一个表的数据的时候,需要关联查询其他表的数据. 需求 首先说一个使用一对一查询的小需求吧:假设我们在查询某一个订单的信息的时候,需要关联查询出创建这个订单对应的用户信 ...

  2. PHP结合memcacheq消息队列解决并发问题

    在处理业务逻辑时有可能遇到高并发问题,例如商城秒杀.微博评论等.如果不做任何措施可能在高瞬间造成服务器瘫痪,如何解决这个问题呢?队列是个不错的选择.队列(Queue)又称先进先出(First In F ...

  3. JNI调用的helloworld(JNI_OnLoad映射方式)

    本示例展示JNI的基本示例,helloworld级别的,不过是用JNI_OnLoad映射的方式. 直接看代码,先看包含native method的Person.java的代码: package hel ...

  4. 【Java基础】反射机制

    反射 反射可以使我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码链接.反射允许我们在编写和执行时,使我们的代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类 ...

  5. 每天一个linux命令(25)--Linux文件属性详解

    Linux 文件或目录的属性主要包括:文件或目录的节点.种类.权限模式.链接数量.所归属的用户和用户组.最近访问或修改的时间等内容.具体情况如下: 命令: ls  -lih 2098120 lrwxr ...

  6. C#同步,异步的理解,包括5.0中await和async(学习笔记)

    之前在工作中一直用的是同步线程,就是先进入画面的load事件,然后在里面进行数据库调用的处理.后面又遇到了公司软件中一些比较古老的代码,一开始在那块古老代码中增加机能的时候,我想用到数据库的数据给画面 ...

  7. 改变 Panel 跟 groupbox边框样式

    更改panel和groupbox的边框颜色因为在控件的属性中没有设置边框颜色的属性只有一个设置边框样式,遂在网络中搜寻出一下方法: panel的边框颜色在paint中重新对颜色进行定义 private ...

  8. x01.Weiqi.13: 鼎力推荐

    鼎力推荐 : 点击后即可观看,小伙子讲的很有深度. 说到深度,自然离不了深度学习.AlphaGo 的横空出世,似乎很有学习的必要. MuGo: 点击下载后,发现是 python,自然免不了一番学习,好 ...

  9. Java日期获取需求大全

    刚进公司,作为熟悉技术,为公司做了一个小的点餐系统的网站,其中大量用到了时间日期作为唯一标示或是显示设置.特总结了一下和大家分享. package com.lucis.ordering.Utils; ...

  10. 用ListView实现对数据库的内容显示

    用ListView实现对数据库的内容显示 创建一个触发机制 ---------(作用)将数据读入ArrayList集合中 MyBase base = new MyBase(); SQLiteDatab ...