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

Posted in :

有些功能,需要新的版本 iOS 才能執行,所以需要判斷 iOS 版本。解法如下:

From iOS 8 we can use the new isOperatingSystemAtLeastVersion method on NSProcessInfo

   NSOperatingSystemVersion ios8_0_1 = (NSOperatingSystemVersion){8, 0, 1};
   if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:ios8_0_1]) {
      // iOS 8.0.1 and above logic
   } else {
      // iOS 8.0.0 and below logic
   }

Beware that this will crash on iOS 7, as the API didn’t exist prior to iOS 8. If you’re supporting iOS 7 and below, you can safely perform the check with

if ([NSProcessInfo instancesRespondToSelector:@selector(isOperatingSystemAtLeastVersion:)]) {
  // conditionally check for any version >= iOS 8 using 'isOperatingSystemAtLeastVersion'
} else {
  // we're on iOS 7 or below
}

解法2號:

Best current version, without need to deal with numeric search within NSString is to define macros(See original answer: Check iPhone iOS Version)

Those macros do exist in github, see: https://github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h

Like this:

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

and use them like this:

if (SYSTEM_VERSION_LESS_THAN(@"5.0")) {
    // code here
}

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
    // code here
}

Outdated version below

to get OS version:

[[UIDevice currentDevice] systemVersion]

returns string, which can be turned into int/float via

-[NSString floatValue]
-[NSString intValue]

like this

Both values (floatValue, intValue) will be stripped due to its type, 5.0.1 will become 5.0 or 5 (float or int), for comparing precisely, you will have to separate it to array of INTs check accepted answer here: Check iPhone iOS Version

NSString *ver = [[UIDevice currentDevice] systemVersion];
int ver_int = [ver intValue];
float ver_float = [ver floatValue];

and compare like this

NSLog(@"System Version is %@",[[UIDevice currentDevice] systemVersion]);
NSString *ver = [[UIDevice currentDevice] systemVersion];
float ver_float = [ver floatValue];
if (ver_float < 5.0) return false;

For Swift 4.0 syntax

below example is just checking if the device is of iOS11 or greater version.

let systemVersion = UIDevice.current.systemVersion
if systemVersion.cgFloatValue >= 11.0 {
    //"for ios 11"
  }
else{
   //"ios below 11")
  }

 


解法3號:

The quick answer …

As of Swift 2.0, you can use #available in an if or guard to protect code that should only be run on certain systems.

if #available(iOS 9, *) {}

In Objective-C, you need to check the system version and perform a comparison.

[[NSProcessInfo processInfo] operatingSystemVersion] in iOS 8 and above.

As of Xcode 9:

if (@available(iOS 9, *)) {}

The full answer …

In Objective-C, and Swift in rare cases, it’s better to avoid relying on the operating system version as an indication of device or OS capabilities. There is usually a more reliable method of checking whether a particular feature or class is available.

Checking for the presence of APIs:

For example, you can check if UIPopoverController is available on the current device using NSClassFromString:

if (NSClassFromString(@"UIPopoverController")) {
    // Do something
}

For weakly linked classes, it is safe to message the class, directly. Notably, this works for frameworks that aren’t explicitly linked as “Required”. For missing classes, the expression evaluates to nil, failing the condition:

if ([LAContext class]) {
    // Do something
}

Some classes, like CLLocationManager and UIDevice, provide methods to check device capabilities:

if ([CLLocationManager headingAvailable]) {
    // Do something
}

Checking for the presence of symbols:

Very occasionally, you must check for the presence of a constant. This came up in iOS 8 with the introduction of UIApplicationOpenSettingsURLString, used to load Settings app via -openURL:. The value didn’t exist prior to iOS 8. Passing nil to this API will crash, so you must take care to verify the existence of the constant first:

if (&UIApplicationOpenSettingsURLString != NULL) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}

Comparing against the operating system version:

Let’s assume you’re faced with the relatively rare need to check the operating system version. For projects targeting iOS 8 and above, NSProcessInfo includes a method for performing version comparisons with less chance of error:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Projects targeting older systems can use systemVersion on UIDevice. Apple uses it in their GLSprite sample code.

// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) {
    displayLinkSupported = TRUE;
}

If for whatever reason you decide that systemVersion is what you want, make sure to treat it as an string or you risk truncating the patch revision number (eg. 3.1.2 -> 3.1).

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *