因为钉钉出了一个打卡黑科技,离线打卡。我们这边老板说要跟进,我们也做一个打卡,我看了看,离线打卡无非就是获取到用户当时打卡的时候、地点等一系列的动作,然后等到有网的时候传到服务器。地点都好说,主要是时间,因为如果9点打卡,用户把时间改成8:58,如果还能打卡成功,那就是bug了。
我们在网上查了一系列的资料发现讲这方面的不多,所以就记录一下
获取准确的本地时间
我们知道iOS获取现在的时间一般用[NSDate date]
,这样获取的时间一般都会跟着本地时间的变化而变化
然后我们发现钉钉第一次进入在没有网络的情况下,也是不能打卡的,说明所谓的黑科技,至少要进行一次网络请求
然后我们就发现了
// 手机运行时长
- (time_t)uptime {
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
time_t now;
time_t uptime = -1;
(void)time(&now);
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0)
{
uptime = now - boottime.tv_sec;
}
return uptime;
}
now是当前的时候,受本地系统时间的影响
sysctl 获取的是上次设备重启的时间,也受本地系统时间的影响
两者之差就是系统从上次设备重启之后所运行的时间
看一组数据
时间变化前(正常时间):
now = 1493706163
boottime.tv_sec = 1493696768
uptime = 9395
我们随意改变一下系统时间(调整后的时间):
now = 1493526460
boottime.tv_sec = 1493516751
uptime = 9709
我们还原系统时间(正常时间):
now = 1493706822
boottime.tv_sec = 1493696768
上次设备重启的时间并没有变化
设备重启后:
now = 1493707140
boottime.tv_sec = 1493707074
上次设备重启的时间发送了变化
这样我们就获取设备运行时间,基本还是准确的
获取网络时间
网络时间只需要设备重启后,获取一次就够了,获取到了之后就在根据获取时的运行时间和后面调用时候的运行时间进行计算
网络时间的获取如果采用Http的获取,会有网络延时,慢的话网络延迟会有十几秒,所以我们选用了一个三方库ios-ntp
这样基本就和钉钉一样了,必须要有一次网络请求之后才能打卡
参考:iOS关于时间的处理
MrPeak大神的文章干货满满的
网友评论