昨天下午工作的时候遇见一个这样的需求,网络请求失败后把请求数据保存到本地,并自动重发3次,时间间隔是10秒,如果3次后还失败的话,下一次启动这个接口的时候,把新数据和保存在本地的数据都要发送,刚开始以为没多少难度,不就是网络请求发送数据嘛,首先脑子里的第一反应就是用定时器,初始化定时器,然后触发相应的方法,设置请求的次数标志,超过3次停止定时器。事实却证明我还没有理解定时器......

  由于是老接口,不能修改,因为产品已经上线,修改会涉及到太多业务,所以只能客户端想办法处理。这样导致的问题就是新数据不能和旧数据一起整合在一起发送,得分两次发送。好吧,那就上吧,我就信心满满的上了。

初始化定时器,遍历本地的数据,分别对应创建一个定时器使用下面的方法,加载到定时器数组

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

然后fire执行。OK,搞定。

bi..bi...bi...bi....bi.....bi......

  擦,定时器全乱了,10s内定时器没啥问题,10s后所以定时器都交替进行。。。这不是坑爹么。。。。

  吸了口气,喝了一杯水,扫了一眼定时器的代码,灵光一闪,会不会是fire用错了,初始化的时候不要立即执行,等初始化完毕的时候在从数组里面拿出定时器,请求成功或者失败三次后再拿出第二个定时器请求。哈哈哈哈哈哈,应该不会错了,就这么办。

bi....bi.....bi.....bi....bi........

  我了个去,稍微好一点了,20秒内的数据是正常的,后面的定时器又交替进行。。。。泥煤呀,甘都得。。。不过已经有进步了,至少20秒是正确的吧,再改改代码应该就可以了,所以立马想一下定时器的执行流程,后来发现会不会是多个定时器和一个定时器的运行是有区别的?因为自己之前基本上都是创建一个定时器就可以了,fire、invalidate使用。没办法,上SOF看看吧。后来才知道原来这两个方法初始化的定时器即使不用fire也会对应的NSTimeInterval后执行,fire只是让他们立即执行,把启动的时间提前到当前,就像一个演唱会本来打算10分钟后开始的,现在因为主唱提前10分钟到了会场,看见粉丝这么热情,提前开始了。

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

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

  可是问题又来了,那既然这样没办法控制定时器的执行,我这个功能岂不是没法做了,有没有什么办法可以控制定时器么,想执行的时候就执行,不想执行的时候就丢掉它。。。。

  查找资料的过程中还发现了几个初始化定时器的方法:两个类方法,一个实例方法。

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

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

- (id)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep;

  这和上面的初始化方法有什么区别么,接着发现者两个类方法和实例方法是要手动添加到NSRunLoop代码执行的:

[[NSRunLoop currentRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];

哈哈哈,这不就是我想要的东东嘛(ˇˍˇ),yo yo check now!

修改定时器的方法,手动添加NSRunLoop执行,然后网络请求不变。。。。OK,搞定。。

bi..bi.....bi....bi......

无压力了。。。。测试一个for循环1000次,没发生什么错误。。。好吧,来个总结。

一直都习惯用最上面的两个方法初始化定时器,然后fire,并且fire的作用只是把定时器的时间提前了,这个是之前使用的时候没有去考虑的。。这种东东在一个定时器下面不会有什么问题,但是多个定时器的话基本上就悲剧。。不过在同一个地方使用多个定时器这样的设计方法我暂时也不知道合理不合理,可能也会有意想不到的的错误,比如内存暴涨,性能受影响之类的,这个暂时没有去考虑,如果你有更好的解决方法,可以交流交流。

那些年我们踩过的坑-NSTimer的更多相关文章

  1. 那些年我们踩过的坑之表单reset

    开发者往往是在一个又一个的坑中成长起来的,自学的开发者尤其如此,刚刚填完一个坑,转身又掉进另一个坑.有些坑很容易就跳出来了,也有些坑能整了一天都没头绪,第二天早上一来发现后面就有一架通往坑外的梯子,坑 ...

  2. 那些年我们踩过的坑,SQL 中的空值陷阱!

    文章目录 NULL 即是空 三值逻辑 空值比较 NOT IN 与空值 函数与空值 DISTINCT.GROUP BY.UNION 与空值 ORDER BY 与空值 空值处理函数 字段约束与空值 SQL ...

  3. 项目中踩过的坑之-sessionStorage

    总想写点什么,却不知道从何写起,那就从项目中踩过的坑开始吧,希望能给可能碰到相同问题的小伙伴一点帮助. 项目情景: 有一个id,要求通过当前网页打开一个新页面(不是当前页面),并把id传给打开的新页面 ...

  4. web开发实战--弹出式富文本编辑器的实现思路和踩过的坑

    前言: 和弟弟合作, 一起整了个智慧屋的小web站点, 里面包含了很多经典的智力和推理题. 其实该站点从技术层面来分析的话, 也算一个信息发布站点. 因此在该网站的后台运营中, 富文本的编辑器显得尤为 ...

  5. "开发路上踩过的坑要一个个填起来————持续更新······(7月30日)"

    欢迎转载,请注明出处! https://gii16.github.io/learnmore/2016/07/29/problem.html 踩过的坑及解决方案记录在此篇博文中! 个人理解,如有偏颇,欢 ...

  6. 【转载】Fragment 全解析(1):那些年踩过的坑

    http://www.jianshu.com/p/d9143a92ad94 Fragment系列文章:1.Fragment全解析系列(一):那些年踩过的坑2.Fragment全解析系列(二):正确的使 ...

  7. Redis Cluster踩过的坑

    Redis Cluster踩过的坑请参考如下链接:http://www.iteye.com/blogs/subjects/Redis_Cluster_Devops

  8. 第八篇:web之前端踩的一些坑

    前端踩的一些坑   前端踩的一些坑 本节内容 事件代理 清除标签的所有事件 bootstrap的模态框自定义方法 ajax在django里面实现post提交 ajax提交数据嵌套 1.事件代理 之前写 ...

  9. 使用ffmpeg视频编码过程中踩的一个坑

           今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,非常多时候一旦思维定势真的挺难突破的.以下是不对的编码结果:                   ...

随机推荐

  1. 查看mysql的版本和端口号

    查看版本:select version(); 查看端口号:show global variables like 'port';

  2. django “如何”系列7:错误汇报

    当你正在运行一个公共的站点的时候,你应该关掉DEBUG设置.这将使你的服务器运行的更快,同时也能预防别有用心的用户从你的错误页面看到你应用的一些详细配置信息.然而,当debug为false的时候,你将 ...

  3. hdu 3371(kruskal)

    Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  4. Linux和Windows双系统安装要点

    这里主要说下CentOS和Windows7的双系统安装遇到的一些问题 一.磁盘分区 这个不得不说下在Windows下坑爹的设定了,如果是用默认的磁盘划分,系统会自己先划出一个100M左右的区,关键还是 ...

  5. echarts官网上的动态加载数据bug被我解决。咳咳/。

    又是昨天,为什么昨天发生了这么多事.没办法,谁让我今天没事可做呢. 昨天需求是动态加载数据,画一个实时监控的折线图.大概长这样. 我屁颠屁颠的把代码copy过来,一运行,caocaocao~bug出现 ...

  6. ubuntu 16.04 LTS安装jenkins服务器

    官方网站:https://jenkins.io/ 这里我们的系统是Ubuntu 16.04,所以选择Ubuntu的版本,另外,为什么选择2.60.3,而不是新的2.77?因为2.60.3是LTS版本, ...

  7. 一:Ionic Framework初体验

    因项目关系,需要开发一个平板使用的应用程序,刚开始以为需要使用Andriod,后来经理提供了一个解决方案,Ionic Framework https://ionicframework.com/ 第一步 ...

  8. 最短路-Bellmanford

    简介: 给定一个图和一个源点,求源点到其余点的最短路径,图中有可能存在负权边. 算法步骤 1.初始化:将除源点外的所有顶点的最短距离估计值 dist[v] ← +∞, dist[s] ←0; 2.迭代 ...

  9. django-BBS(2)

    昨天设计了数据库和数据表,今天来进行页面前端的设计, 1.首先去bootstarp上,下载相应的模板和配置文件,添加到对应的位置 2.在templates中添加许多许多的html页面 如下     并 ...

  10. Java-多线程编程(一)

    创建多线程 [Thread class]1.继承Thread类,重写run() [Runnable接口]2.实现Runnable接口,重写run() [*Callable接口]3.实现Callable ...