Getting system uptime in iOS/Swift

前端 未结 4 1191
被撕碎了的回忆
被撕碎了的回忆 2020-12-10 00:03

Is there a way to get system uptime in iOS (using Swift)? What I need is to measure time without having to worry about the user changing the time. In Android there\'s a

相关标签:
4条回答
  • 2020-12-10 00:18

    You can call ObjC code from Swift:

    print(SystemUtil().uptime());
    

    Write a ObjC class like the accepted answer you mentioned: Getting iOS system uptime, that doesn't pause when asleep.

    SystemUtil.h for interface:

    #import <Foundation/Foundation.h>
    
    @interface SystemUtil : NSObject
    
    - (time_t)uptime;
    
    @end
    

    SystemUtil.m for implementation:

    #import "SystemUtil.h"
    #include <sys/sysctl.h>
    
    @implementation SystemUtil
    
    - (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;
    }
    
    @end
    

    And don't forget to include a <Project>-Bridge-Header.h with the following content so that you can use the ObjC class from Swift (<Project> is your project name):

    #import "SystemUtil.h"
    
    0 讨论(0)
  • 2020-12-10 00:19

    As you ask for a pure-Swift solution, I converted the ObjC code from the answer you mentioned Getting iOS system uptime, that doesn't pause when asleep.

    func uptime() -> time_t {
        var boottime = timeval()
        var mib: [Int32] = [CTL_KERN, KERN_BOOTTIME]
        var size = strideof(timeval)
    
        var now = time_t()
        var uptime: time_t = -1
    
        time(&now)
        if (sysctl(&mib, 2, &boottime, &size, nil, 0) != -1 && boottime.tv_sec != 0) {
            uptime = now - boottime.tv_sec
        }
        return uptime
    }
    
    // print(uptime())
    

    To make it a bit prettier, we can use sysctlbyname instead of sysctl:

    // var mib: [Int32] = [CTL_KERN, KERN_BOOTTIME]
    sysctlbyname("kern.boottime", &boottime, &size, nil, 0)
    
    0 讨论(0)
  • 2020-12-10 00:27

    This is a solution in Swift 4.

     var boottime = timeval()
     var size = MemoryLayout<timeval>.stride
     sysctlbyname("kern.boottime", &boottime, &size, nil, 0) 
    
    0 讨论(0)
  • 2020-12-10 00:45

    Updated for Swift 5 and straight from ADF post here:

    func bootTime() -> Date? {  
        var tv = timeval()  
        var tvSize = MemoryLayout<timeval>.size  
        let err = sysctlbyname("kern.boottime", &tv, &tvSize, nil, 0);  
        guard err == 0, tvSize == MemoryLayout<timeval>.size else {  
            return nil  
        }  
        return Date(timeIntervalSince1970: Double(tv.tv_sec) + Double(tv.tv_usec) / 1_000_000.0)  
    }
    

    "Be aware that this time will change if the system clock changes, that is, the value is the boot time relative to the current system clock."

    0 讨论(0)
提交回复
热议问题