iOS倒计时设计思路和一个系统时间的坑
2017-05-08 18:32
288 查看
个人知识点记录,仅供参考
1.用GCD定时器更准确2.当前时间要用服务器时间
3.如何考虑手机锁屏线程休眠
4.如何做到tableViewCell里面放倒计时
5.到期时间不变,当前时间在变,主要操作的是这个差值
Demo分析
1.创建GCD定时器 Demo用NSDate来模拟服务器当前时间@property (nonatomic,strong) dispatch_source_t timer; - (void)refreshDataForCountDown{ if (!self.timer) { __weak typeof(self) weakSelf = self; self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1.0f * NSEC_PER_SEC, 0.0f * NSEC_PER_SEC); dispatch_source_set_event_handler(self.timer, ^{ @autoreleasepool { NSLog(@"定期器跑起来了。。。"); NSTimeInterval timerTop = ([[NSProcessInfo processInfo] systemUptime] - weakSelf.appStartTimeTop); NSTimeInterval timerBottom = ([weakSelf uptime] - weakSelf.appStartTimeBottom); weakSelf.topLabel.text = [weakSelf.formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:weakSelf.serverTimeTop + timerTop]]; weakSelf.bottomLabel.text = [weakSelf.formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:weakSelf.serverTimeBottom + timerBottom]]; } }); dispatch_resume(self.timer); } }
2.获取当前设备系统/进程的时间
进程时间
[[NSProcessInfo processInfo] systemUptime]
系统内核时间(这里有介绍该方法)
int sysctl(int *, u_int, void *, size_t *, void *, size_t);
这里先针对Demo分析下,这两个获取当前系统时间的方法,主要用他们来给服务器时间补差值,比如说你获取到服务器时间之后,啥都没做,过了几秒钟,你肯定需要记录系统时间,把服务器时间加上这个差值,就是时时模拟出来的服务器时间,OK这个没问题了,那么问题来了,当你手机开着的时候,没问题的,你看不出来的,但是你锁屏你试试,等几分钟来看看,你会发现NSProcessInfo对应下的时间慢了。。。。。
直接看这个吧,这里有详细讨论
但是有个注意点,我也被恶心了一下午,测试的时候记得把你的数据线拔了,不然你锁屏的时候进程也不会休眠的。。
看下效果,记住你拔掉你的数据线,锁屏,等几分钟来看看,两个时间就不准了
总结:NSProcessInfo是不准确的,我们要用内核的系统时间,这样才不受线程休眠的影响,你无论什么状态下获取到都是正确的时间差,加上你请求到的服务器时间,就是完美的当前时间
- (NSTimeInterval)uptime { struct timeval boottime; int mib[2] = {CTL_KERN, KERN_BOOTTIME}; size_t size = sizeof(boottime); struct timeval now; struct timezone tz; gettimeofday(&now, &tz); double uptime = -1; if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) { uptime = now.tv_sec - boottime.tv_sec; uptime += (double)(now.tv_usec - boottime.tv_usec) / 1000000.0; } return uptime; }
3.重新刷新一次时间就恢复了
- (IBAction)refreshTime:(id)sender { self.serverTimeTop = [[NSDate date] timeIntervalSince1970]; self.serverTimeBottom = [[NSDate date] timeIntervalSince1970]; self.appStartTimeTop = [[NSProcessInfo processInfo] systemUptime]; self.appStartTimeBottom = [self uptime]; }
如果你不刷新,你获取到的systemUptime已经滞后了(线程休眠导致的),那么你算出来的差值自然已经滞后了,但是内核的时间是肯定准确的,如果你刷新一次,又同步了两个时间,又恢复了,这个Demo只是验证NSProcessInfo不能用来进行获取进程行走的时间,稍微分析下倒计时逻辑
倒计时思路 —>>有问题的话可以留言交流
1.核心思想是只操作数据源,KVO的方式进行UI倒计时2.通过请求数据获取到一个到期时间,然后根据系统时间算于出当前时间的差值
3.在适当的地方开启定时器修改数据源的差值字段,cell进行监听刷新UI
4.手机锁屏的时候切换到后台,再次进来你要再次根据当前服务器时间刷新这个差值,重新进行当前的倒计时,如果不刷新,线程休眠,你的差值是不变的,而系统时间在走,因此都要跟着变,就在App进入前台的时候重新给数据源的差值进行计算赋值(这里如何保证系统时间准确,记得用sysctl内核方法去获取)
相关文章推荐
- 设计一个如下图所示窗体:该窗体自动位于屏幕中央;大小不可调;最小化、最大化按钮不可用;窗体标题为“烟台大学”。在该窗体上,放置一个按钮、一个标签。单击按钮时,在标签上显示当前系统时间。
- Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程
- 系统设计 - IOS 程序插件及功能动态更新思路
- iOS开发:代码通用性以及其规范 第二篇(猜想iOS中实现TableView内部设计思路(附代码),以类似的思想实现一个通用的进度条)
- 有1000亿条记录,每条记录由url,ip,时间组成,设计一个系统能够快速查询以下内容(程序设计题)
- C#--第11周实验--任务1(建立Windows窗体应用程序)--设计一个窗体--单击按钮时,在标签上显示当前系统时间
- Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程
- 有1000亿条记录,每条记录由url,ip,时间组成,设计一个系统能够快速查询以下内容
- 高并发 强实时 强一致数据库业务系统设计的一个思路
- Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程
- iOS设计模式-开发思路提问(系列1:一个Button的三种状态怎样切换?)
- C#--第11周实验--任务1(建立Windows窗体应用程序)--设计一个窗体--单击按钮时,在标签上显示当前系统时间 .
- 【一个批量计算的调度系统的设计与实现】如果需要对成千上万的网络抓包数据文件在规定的时间内进行解析,应该怎么做?
- 设计一个图书借阅管理系统需要如何分析
- 权限系统-2:概念模型和设计思路整理
- 系统设计之时间维度[数据仓库]
- 一个典型的嵌入式系统设计和实现
- 面向对象系统分析设计过程-整体思路
- 全能后台管理系统设计思路
- 一个.net的系统的AOP设计思路二——页面控件校验映射