Home » Ios » Check OS version in Swift?

Check OS version in Swift?

Posted by: admin November 30, 2017 Leave a comment

Questions:

I’m trying to check system information in Swift. I figured out, that it could be achieved by code:

var sysData:CMutablePointer<utsname> = nil
let retVal:CInt = uname(sysData)

I have two problems with this code:

  1. What should be sysData’s initial value? This example gives -1 in retVal probably because sysData is nil.
  2. How can I read information from sysData?
Answers:

For iOS, try:

var systemVersion = UIDevice.current.systemVersion

For OS X, try:

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

If you just want to check if the users is running at least a specific version, you can also use the following Swift 2 feature which works on iOS and OS X:

if #available(iOS 9.0, *) {
    // use the feature only available in iOS 9
    // for ex. UIStackView
} else {
    // or use some work around
}

BUT it is not recommended to check the OS version. It is better to check if the feature you want to use is available on the device than comparing version numbers.
For iOS, as mentioned above, you should check if it responds to a selector;
eg.:

if (self.respondsToSelector(Selector("showViewController"))) {
    self.showViewController(vc, sender: self)
} else {
    // some work around
}

Questions:
Answers:

Update:
Now you should use new availability checking introduced with Swift 2:
e.g. To check for iOS 9.0 or later at compile time use this:

if #available(iOS 9.0, *) {
    // use UIStackView
} else {
    // show sad face emoji
}

or can be used with whole method or class

@available(iOS 9.0, *)
func useStackView() {
    // use UIStackView
}

For more info see this.

Run time checks:

if you don’t want exact version but want to check iOS 9,10 or 11 using if:

let floatVersion = (UIDevice.current.systemVersion as NSString).floatValue

EDIT:
Just found another way to achieve this:

let iOS8 = floor(NSFoundationVersionNumber) > floor(NSFoundationVersionNumber_iOS_7_1)
let iOS7 = floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_7_1)

Questions:
Answers:

I made helper functions that were transferred from the below link into swift:

How can we programmatically detect which iOS version is device running on?

func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
}

func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
}

It can be used like so:

SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO("7.0")

Questions:
Answers:

I made this Singleton for simple use, created an IOSVersion.swift file and added this code :

import UIKit

public class IOSVersion {
    class func SYSTEM_VERSION_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
    }

    class func SYSTEM_VERSION_GREATER_THAN(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
    }

    class func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
    }

    class func SYSTEM_VERSION_LESS_THAN(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
    }

    class func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
    }
}

USE :

IOSVersion.SYSTEM_VERSION_EQUAL_TO("8.0")
IOSVersion.SYSTEM_VERSION_LESS_THAN("8.0")

Thanks @KVISH

Edit Swift 2 :

if #available(iOS 9.0, *) {
    // ? 
} else {
    // ?
}

Questions:
Answers:

Swift 3.0

We dont need to create extension since ProcessInfo gives us the version info. You can see sample code for iOS as below.

let os = ProcessInfo().operatingSystemVersion
switch (os.majorVersion, os.minorVersion, os.patchVersion) {
case (8, 0, _):
    print("iOS >= 8.0.0, < 8.1.0")
case (8, _, _):
    print("iOS >= 8.1.0, < 9.0")
case (9, _, _):
    print("iOS >= 9.0.0")
default:
    // this code will have already crashed on iOS 7, so >= iOS 10.0
    println("iOS >= 10.0.0")
}

Reference: http://nshipster.com/swift-system-version-checking/

Questions:
Answers:

If you’re using Swift 2 and you want to check the OS version to use a certain API, you can use new availability feature:

if #available(iOS 8, *) {
    //iOS 8+ code here.
}
else {
    //Code for iOS 7 and older versions.
    //An important note: if you use #availability, Xcode will also 
    //check that you don't use anything that was introduced in iOS 8+
    //inside this `else` block. So, if you try to use UIAlertController
    //here, for instance, it won't compile. And it's great.
}

I wrote this answer because it is the first question in Google for the swift 2 check system version query.

Questions:
Answers:

Update for Swift 3.0+

func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedSame
}

func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedAscending
}

func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedDescending
}

Questions:
Answers:
let Device = UIDevice.currentDevice()
let iosVersion = NSString(string: Device.systemVersion).doubleValue

let iOS8 = iosVersion >= 8
let iOS7 = iosVersion >= 7 && iosVersion < 8

and check as

if(iOS8)
{

}
else 
{
}  

Questions:
Answers:

Mattt Thompson shares a very handy way

switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
case .OrderedSame, .OrderedDescending:
    println("iOS >= 8.0")
case .OrderedAscending:
    println("iOS < 8.0")
}

Questions:
Answers:

Checking MacOS and iOS version in Swift 3

IOS

code

    extension UIDevice {
    var iOS: Double? {
        if UIDevice.current.systemName == "iOS" {
            if let iosVersion = UIDevice.current.systemVersion.toDouble {
                return iosVersion
            }
        }
        return nil
    }
}

extension String {

    var toDouble: Double? {

        if let iosVersion = Double(self) {
            return iosVersion
        }

        var arr = components(separatedBy: ".")
        if arr.count >= 1 {
            var integerPart = 0
            var floatPart = 0

            if let _integerPart = Int(arr[0]), !arr[0].isEmpty{
                integerPart = _integerPart
            }

            if let _floatPart = Int(arr[1]), !arr[1].isEmpty{
                floatPart = _floatPart
            }

            return Double("\(integerPart).\(floatPart)")
        }
       return nil
    }
}

version string transformation sample

var stringVersion = "10.1.1"
print(stringVersion.toDouble!) // print 10.1
stringVersion = ".5.35"
print(stringVersion.toDouble!) // print 0.5
stringVersion = "..35"
print(stringVersion.toDouble!) // print 0.0

usage

if let iosVersion = UIDevice.current.iOS {
    if iosVersion >= 8.0 {
        print("current version: \(iosVersion)")
    }
}

MacOS

code

extension ProcessInfo {
    var OS: Double? {
        let result = "\(ProcessInfo.processInfo.operatingSystemVersion.majorVersion).\(ProcessInfo.processInfo.operatingSystemVersion.minorVersion)"
        return Double(result)
    }
}

usage

// check os version
if let systemVersion = ProcessInfo.processInfo.OS {
    if systemVersion >= 10.1 {
        print("current version: \(systemVersion)")
    }
}

Questions:
Answers:

The easiest and the simplest way to check system version (and a lot of other versions) in Swift 2 and higher is:

if #available(iOS 9.0, *) { // check for iOS 9.0 and later

}

Also, with #available you can check versions of these:

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift

Questions:
Answers:

Note: Available in iOS 8.0 and later. OS X v10.10 and later

var majorVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.majorVersion }
var minorVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.minorVersion }
var patchVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.patchVersion }
var myOSVersion:  String { return NSProcessInfo.processInfo().operatingSystemVersionString        }

Questions:
Answers:

Based on Matt Thompson’s answer, here is a method with respective unit tests that works with Swift and Objective-c on iOS 7 and above (including iOS 9 which no longer let’s you check the NSFoundationNumber):

+ (BOOL) isAtLeastOSVersion:(NSString *)osVersion
{
    switch ([[UIDevice currentDevice].systemVersion compare:osVersion options:NSNumericSearch]) {
        case NSOrderedSame:
        case NSOrderedDescending:
            return YES;
        default:
            return NO;
    }
}  

.

@interface ANFakeCurrDevice : NSObject
@property (nonatomic, strong) NSString *systemVersion;
@end
@implementation ANFakeCurrDevice
@end


@implementation MyHelperClassUnitTests

- (void)setUp {
    [super setUp];
}

- (void)tearDown {
    [super tearDown];
}

- (void)test_isAtLeastOSVersion
{
    id deviceMock = [OCMockObject niceMockForClass:[UIDevice class]];
    ANFakeCurrDevice *fakeCurrDevice = [ANFakeCurrDevice new];
    fakeCurrDevice.systemVersion = @"99.9.9";
    [[[deviceMock stub] andReturn:fakeCurrDevice] currentDevice];
    XCTAssertTrue([[UIDevice currentDevice].systemVersion isEqualToString:@"99.9.9"]);

    fakeCurrDevice.systemVersion = @"1.0.1";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1.0"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"1.0.2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"1.1.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.1.0"]);


    fakeCurrDevice.systemVersion = @"8.4.0";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"7.0.1"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"8.4.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"8.4.2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0.2"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"] && ![ANConstants isAtLeastOSVersion:@"9.0"]);

    fakeCurrDevice.systemVersion = @"8.4.1";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"] && ![ANConstants isAtLeastOSVersion:@"9.0"]);
}


@end

Questions:
Answers:

Also if you want to check WatchOS.

Swift

let watchOSVersion = WKInterfaceDevice.currentDevice().systemVersion
print("WatchOS version: \(watchOSVersion)")

Objective-C

NSString *watchOSVersion = [[WKInterfaceDevice currentDevice] systemVersion];
NSLog(@"WatchOS version: %@", watchOSVersion);

Questions:
Answers:
let osVersion = NSProcessInfo.processInfo().operatingSystemVersion
let versionString = osVersion.majorVersion.description + "." + osVersion.minorVersion.description + "." + osVersion.patchVersion.description
print(versionString)

Questions:
Answers:

Get current version of system and split it.
So you can get major and minor version.

let sys_version = UIDevice.current.systemVersion
let all_version = sys_version.components(separatedBy: ".")
print("Major version : \(all_version[0])")
print("Minor version : \(all_version[1])")

Questions:
Answers:

Most of sample codes written here will get unexpected result with extra-zero versions. For example,

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedAscending
}

This method won’t return true with passed version “10.3.0” in iOS “10.3”. This kind of result does not make sense and they must be regarded as same version. To get accurate comparison result, we must consider comparing all of number components in version string. Plus, providing global methods in all capital letters is not a good way to go. As version type we use in our SDK is a String, it’s make sense that extending comparing functionality in String.

To compare system version, all of the following examples should work.

XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThan: "99.0.0"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(equalTo: UIDevice.current.systemVersion))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThan: "3.5.99"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThanOrEqualTo: "10.3.0.0.0.0.0.0"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThanOrEqualTo: "10.3"))

You can check it out in my repository here
https://github.com/DragonCherry/VersionCompare