iOS: Get Alphanumeric System Version

1 min read May 06, 2017

iOS: Get Alphanumeric System Version

Table of Content

This is the way to get the alphanumeric system version like 16E195 in 10.3(16E195).

Objective-C Way

#import <sys/sysctl.h>

- (NSString *)alphanumericSystemVersion {
    int mib[2] = {CTL_KERN, KERN_OSVERSION};
    u_int namelen = sizeof(mib) / sizeof(mib[0]);
    size_t bufferSize = 0;

    NSString *alphanumeric = nil;

    // Get the size for the buffer
    sysctl(mib, namelen, NULL, &bufferSize, NULL, 0);

    u_char buildBuffer[bufferSize];
    int result = sysctl(mib, namelen, buildBuffer, &bufferSize, NULL, 0);

    if (result >= 0) {
        alphanumeric = [[NSString alloc] initWithBytes:buildBuffer length:bufferSize encoding:NSUTF8StringEncoding];
    }

    return alphanumeric;
}

Swift 3 Way

First, we need:

public enum SysctlError: Error {
    case unknown
    case malformedUTF8
    case invalidSize
    case posixError(POSIXErrorCode)
}

public func sysctl(levels: [Int32]) throws -> String {
    let temp = try levels.withUnsafeBufferPointer() { levelsPointer throws -> [Int8] in
        // Preflight the request to get the required data size
        var requiredSize = 0
        let preFlightResult = Darwin.sysctl(UnsafeMutablePointer<Int32>(mutating: levelsPointer.baseAddress), UInt32(levels.count), nil, &requiredSize, nil, 0)
        if preFlightResult != 0 {
            throw POSIXErrorCode(rawValue: errno).map { SysctlError.posixError($0) } ?? SysctlError.unknown
        }

        // Run the actual request with an appropriately sized array buffer
        let data = Array<Int8>(repeating: 0, count: requiredSize)
        let result = data.withUnsafeBufferPointer() { dataBuffer -> Int32 in
            return Darwin.sysctl(UnsafeMutablePointer<Int32>(mutating: levelsPointer.baseAddress), UInt32(levels.count), UnsafeMutableRawPointer(mutating: dataBuffer.baseAddress), &requiredSize, nil, 0)
        }
        if result != 0 {
            throw POSIXErrorCode(rawValue: errno).map { SysctlError.posixError($0) } ?? SysctlError.unknown
        }

        return data
    }
    let str = temp.withUnsafeBufferPointer() { dataPointer -> String? in
        dataPointer.baseAddress.flatMap {
            String(validatingUTF8: $0)
        }
    }
    guard let s = str else {
        throw SysctlError.malformedUTF8
    }
    return s
}

Then:

public extension UIDevice {
    public var alphanumericSystemVersion: String? {
        retrun try? sysctl(levels: [CTL_KERN, KERN_OSVERSION])
    }
}

Other

If you want a full string like Version 10.2.1 (Build 14D27), use this:

let os = ProcessInfo.processInfo.operatingSystemVersionString
Picsew | Ezra