iOS內部時鍾


1.什么是內部時鍾

     在我們做iOS開發的過程中,我們經常要與時間打交道,[NSDate date]是我們常用的取時間的一種方式,但是[NSDate date] 這種方式只能取系統的當前時間。也就是說:當前我們手機的時間是什么時間,取出來的值,就是多少。

    如果用戶把系統的時間改了呢?那么[NSDate date]取出來的值,還是我們想要的嗎???在一些應用的開發中,我們在沒有網絡的狀態下,不能取網絡時間,依靠系統時間,是可以篡改的。所以這個時候,我們要自己要在程序的內部定制一個自己的內部時鍾。

 

2.實現內部時鍾的思路

    1.要有一個時間作為基本的參照點(一般應用都會與服務器打交道,所以發請求給服務器,取服務器的時間是比較合適的)

    2.要有一個標記點(一般取待機時長)

    3.在每次進入程序的時候,或者登錄的時候,取服務器的時間存起來,然后再取當前的待機時間存起來,每次要獲取當前時間的時候,再取待機時長跟之前的存儲的待機時長比較,獲得差值。將存儲的服務器時間加上差值,就獲得想要的當前時間。

 

3.具體實現步驟

   0.用到的宏:

//開機時間
#define SWStartTime  @"startTime"

//服務器時間
#define SWServerTime @"serverTime"

//登錄時的待機時長
#define SWSinceNow @"sinceNow"

 

   1.獲取待機時長


/** * 待機時間(從系統啟動的那一刻開始獲取的時間間隔) */ + (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; }

 2.存儲服務器時間及待機時長

/**
 *  存儲服務器時間及待機時長
 *
 *  @param serverTime 服務器時間
 */
+ (void)firstTimeWithLogin:(NSString *)serverTime
{
        NSTimeInterval timer = (NSTimeInterval)[self uptime];
        NSString *sinceNow = [NSString stringWithFormat:@"%f",timer];
        
        NSUserDefaults *UserDefaults = [NSUserDefaults standardUserDefaults];
        //存儲登錄時獲取的服務器時間
        [UserDefaults setObject:serverTime forKey:SWServerTime];
        //存儲登錄時獲取的待機時長
        [UserDefaults setObject:sinceNow forKey:SWSinceNow];
   
}

 3.獲得當前的時間(以服務器時間為基准)

+ (NSDate *)dateOfNow
{
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    
    NSUserDefaults *UserDefaults = [NSUserDefaults standardUserDefaults];
    //取出登錄時獲取的服務器時間
    NSString * serverText = [UserDefaults objectForKey:SWServerTime];
    NSDate *FirstServer = [formatter dateFromString:serverText];
    
    NSString *firstText = [UserDefaults objectForKey:SWSinceNow];
    CGFloat first = firstText.floatValue;
    NSTimeInterval timer = (NSTimeInterval)[self uptime];
    
    CGFloat second = (CGFloat)timer;
    
    //差值
    CGFloat finaly = second - first;
    NSTimeInterval interval = (NSTimeInterval)finaly;
    
    //最后的時間
    NSDate *finalyDate = [FirstServer dateByAddingTimeInterval:interval];
    return finalyDate;
}

 4.深度探討

  •    為什么獲取待機時間不用SystemUptime這種方法?

答案 :SystemUptime這種獲取待機時間的方式在我們設備深度睡眠的時候,獲取的值會有誤差,而上面我所用的方法不會。親測!!!

  •    如果我要獲取手機的開機時間,怎么辦?

答案 :

/**
 *  獲得開機時間
 */
+ (NSString *)getUpTime{
    NSString * proc_useTiem;
    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, 0};
    size_t miblen = 4;
    size_t size;
    //返回0,成功;返回-1,失敗
    int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
    
    struct kinfo_proc * process = NULL;
    struct kinfo_proc * newprocess = NULL;
    do
    {
        size += size / 10;
        newprocess = realloc(process, size);
        if (!newprocess)
        {
            if (process)
            {
                free(process);
                process = NULL;
            }
            return nil;
        }
        process = newprocess;
        st = sysctl(mib, miblen, process, &size, NULL, 0);
        
    }
    while (st == -1 && errno == ENOMEM);
    if (st == 0)
    {
        if (size % sizeof(struct kinfo_proc) == 0)
        {
            int nprocess = size / sizeof(struct kinfo_proc);
            if (nprocess)
            {
                for (int i = nprocess - 1; i >= 0; i--)
                {
                    @autoreleasepool{
                        
                        //進程的時間
                        double t = process->kp_proc.p_un.__p_starttime.tv_sec;
                        double s = process->kp_proc.p_un.__p_starttime.tv_usec;
                        double finaly = t + s *0.000001;
//將其轉為具體時間 proc_useTiem
= [self timeWithBoot:finaly]; } } free(process); process = NULL; return proc_useTiem; } } } return nil; }

 

/**
 *  轉為具體時間
 */
+ (NSString *)timeWithBoot:(double)interval
{
    NSDateFormatter *format = [[NSDateFormatter alloc]init];
    format.timeZone = [NSTimeZone timeZoneWithName:@"shanghai"];
    [format setDateStyle:NSDateFormatterMediumStyle];
    [format setTimeStyle:NSDateFormatterShortStyle];
    //注意先后順序
    [format setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];
 NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval]; NSString *bootTime = [format stringFromDate:date]; return bootTime; }

 

PS:如有問題請留言或關注我的新浪微博http://weibo.com/3216725234私信我!!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM