Object-C定时器,封装GCD定时器的必要性!!! (一)
实际项目开发中经常会遇到延迟某件任务的执行,或者让某件任务周期性的执行。然后也会在某些时候需要取消掉之前延迟执行的任务。
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定时器的必要性!!! (一)的更多相关文章
- Object-C定时器,封装GCD定时器的必要性!!! (二)
上一篇:Object-C定时器,封装GCD定时器的必要性!!! (一) 上一篇认识了Object-C中的几种定时器,这一篇将Dispatch定时器(GCD定时器)封装起来. p.p1 { margin ...
- GCD定时器
// // ViewController.m // GCD 定时器 // // #import "ViewController.h" NSInteger count = ; @in ...
- IOS GCD定时器
提到定时器,NStimer肯定是我们最为熟悉的. 但是NStimer有着很大的缺点,并不准确. 通俗点说,就是它该做他的事了,但是由于其他事件的影响,Nstimer会放弃他应该做的. 而GCD定时器, ...
- runloop 和 CFRunLoop - 定时器 - NSTimer 和 GCD定时器
1. 2. #import "ViewController.h" @interface ViewController () @property (nonatomic, strong ...
- 关于普通定时器与高级定时器的 PWM输出的初始化的区别
不管是普通定时器还是高级定时器,你用哪个通道,就在程序里用OC多少.比如CH3对应OC3 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_ ...
- [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 ...
- 14.TCP的坚持定时器和保活定时器
一.坚持定时器 1.坚持定时器的由来 TCP通过让接收方指明希望从发送方接受的窗口大小来进行流量控制.设置窗口大小为0可以组织发送方传送数据,直至窗口变为非0为止. ...
- TCP的定时器系列 — 保活定时器
主要内容:保活定时器的实现,TCP_USER_TIMEOUT选项的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 原理 HTTP有Keepaliv ...
- TCP的定时器系列 — SYNACK定时器
主要内容:SYNACK定时器的实现,TCP_DEFER_ACCPET选项的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 在上一篇博客中,已经连带 ...
随机推荐
- javase基础回顾(一)ArrayList深入解析 解读ArrayList源代码(JDK1.8.0_92)
我们在学习这一块内容时需要注意的一个问题是 集合中存放的依然是对象的引用而不是对象本身. List接口扩展了Collection并声明存储一系列元素的类集的特性.使用一个基于零的下标,元素可以通过它们 ...
- MySQL主从复制的原理和实践操作
MySQL 主从(MySQL Replication),主要用于 MySQL 的实时备份.高可用HA.读写分离.在配置主从复制之前需要先准备 2 台 MySQL 服务器. 一.MySQL主从原理 1. ...
- Keepalived安装与配置
下载并解压Keepalived安装包到两台nginx所在的服务器 192.168.200.1 192.168.200.2 执行编译安装(安装目录设置为 /usr/local/kee ...
- Docker入门01——Image
1.获取镜像 2.列出镜像 3.创建镜像 3.1 修改已有镜像 3.2 使用Dockerfile创建镜像 创建Dickerfile文件 使用build来创建镜像 使用新创建的镜像来启动容器 4.移除镜 ...
- 【译】Nodejs最好的ORM - TypeORM
TypeORM github: https://github.com/typeorm/typeorm 这篇译文是从TypeORM github上的使用说明上翻译过来的,已经提交PR并merge到库中了 ...
- 华为HG8245 电信 光猫破解获取超级密码
这款光猫是 猫+无线路由器一体的 默认没有打开路由功能. 光猫背后的用户名和密码是有限制的没人什么用处,如果要打开路由功能就得要有 超级用户名和密码 不然就算收的到无线连的起也上不了网 .这时就需要 ...
- jQuery_小测试
1.在div元素中,包含了一个<span>元素,通过has选择器获取<div>元素中的<span>元素的语法是? 提示使用has() 2.在<ul>元素 ...
- Cocos2d-x shader学习3: sprite描边(Outline)
Cocos2d-x 3.x的label使用了freetype字体引擎(http://www.freetype.org/),可以很轻松的实现描边和阴影效果.所以本篇文章只针对于sprite来实现描边效果 ...
- Linux下随机生成密码的命令总结
有时候经常为如何设置一个安全.符合密码复杂度的密码而绞尽脑汁,说实话,这实在是一个体力活而且浪费时间,更重要的是设置密码的时候经常纠结.终于有一天实在忍不住了,于是学习.整理了一下如何使用Linux下 ...
- 九度OJ题目1076:N的阶乘 (java)运用BigInteger的例子。
题目描述: 输入一个正整数N,输出N的阶乘. 输入: 正整数N(0<=N<=1000) 输出: 输入可能包括多组数据,对于每一组输入数据,输出N的阶乘 样例输入: 4 5 15 样例输出: ...