如何查看iOS版本?

我想检查设备的iOS版本是否大于3.1.3我尝试过这样的事情:

[[UIDevice currentDevice].systemVersion floatValue]

但它不工作,我只想要一个:

if (version > 3.1.3) { }

我怎样才能做到这一点?

521365 次浏览

尝试:

NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"3.1.3" options: NSNumericSearch];if (order == NSOrderedSame || order == NSOrderedDescending) {// OS version >= 3.1.3} else {// OS version < 3.1.3}

快速回答…


从Swift 2.0开始,您可以在ifguard中使用#available来保护只能在某些系统上运行的代码。

if #available(iOS 9, *) {}


在Objective-C中,您需要检查系统版本并进行比较。

[[NSProcessInfo processInfo] operatingSystemVersion]iOS8及以上。

从Xcode 9开始:

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


完整答案…

在Objective-C和Swift中,在极少数情况下,最好避免依赖操作系统版本作为设备或操作系统功能的指示。通常有一种更可靠的方法来检查特定功能或类是否可用。

检查API的存在:

例如,您可以使用NSClassFromString检查当前设备上是否有UIPopoverController可用:

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

对于弱链接的类,直接向类发送消息是安全的。值得注意的是,这适用于未显式链接为“必需”的框架。对于缺失的类,表达式的计算结果为nil,条件失败:

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

一些类,如CLLocationManagerUIDevice,提供了检查设备功能的方法:

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

检查符号的存在:

偶尔,你必须检查是否存在常量。这是在iOS8中引入UIApplicationOpenSettingsURLString时出现的,用于通过-openURL:加载设置应用程序。该值在iOS8之前不存在。将nil传递给此API会崩溃,因此你必须首先注意验证常量的存在:

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

与操作系统版本比较:

假设你很少需要检查操作系统版本。对于针对iOS8及更高版本的项目,NSProcessInfo包含了一种执行版本比较的方法,错误几率更小:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

针对旧系统的项目可以在UIDevice上使用systemVersion。Apple在他们的GLSprite示例代码中使用它。

// 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;}

如果出于某种原因您决定systemVersion是您想要的,请确保将其视为字符串,否则您可能会截断补丁修订号(例如3.1.2->3.1)。

/**  System Versioning Preprocessor Macros*/
#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)
/**  Usage*/
if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {...}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {...}

一般来说,最好询问一个对象是否可以执行给定的选择器,而不是检查版本号来决定它是否必须存在。

当这不是一个选项时,你确实需要在这里小心一点,因为[@"5.0" compare:@"5" options:NSNumericSearch]返回NSOrderedDescending,这很可能根本不是故意的;我可能会在这里期待NSOrderedSame。这至少是一个理论上的问题,在我看来值得辩护。

同样值得考虑的是不能合理比较的坏版本输入的可能性。Apple提供了三个预定义的常量NSOrderedAscendingNSOrderedSameNSOrderedDescending,但我可以想到一个用于NSOrderedUnordered的东西,如果我不能比较两个东西,我想返回一个指示这一点的值。

更重要的是,Apple有一天会扩展他们的三个预定义常量以允许各种返回值,这并非不可能,从而使比较!= NSOrderedAscending变得不明智。

说到这里,考虑以下代码。

typedef enum {kSKOrderedNotOrdered = -2, kSKOrderedAscending = -1, kSKOrderedSame = 0, kSKOrderedDescending = 1} SKComparisonResult;
@interface SKComparator : NSObject+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo;@end
@implementation SKComparator+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo {if (!vOne || !vTwo || [vOne length] < 1 || [vTwo length] < 1 || [vOne rangeOfString:@".."].location != NSNotFound ||[vTwo rangeOfString:@".."].location != NSNotFound) {return SKOrderedNotOrdered;}NSCharacterSet *numericalCharSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];NSString *vOneTrimmed = [vOne stringByTrimmingCharactersInSet:numericalCharSet];NSString *vTwoTrimmed = [vTwo stringByTrimmingCharactersInSet:numericalCharSet];if ([vOneTrimmed length] > 0 || [vTwoTrimmed length] > 0) {return SKOrderedNotOrdered;}NSArray *vOneArray = [vOne componentsSeparatedByString:@"."];NSArray *vTwoArray = [vTwo componentsSeparatedByString:@"."];for (NSUInteger i = 0; i < MIN([vOneArray count], [vTwoArray count]); i++) {NSInteger vOneInt = [[vOneArray objectAtIndex:i] intValue];NSInteger vTwoInt = [[vTwoArray objectAtIndex:i] intValue];if (vOneInt > vTwoInt) {return kSKOrderedDescending;} else if (vOneInt < vTwoInt) {return kSKOrderedAscending;}}if ([vOneArray count] > [vTwoArray count]) {for (NSUInteger i = [vTwoArray count]; i < [vOneArray count]; i++) {if ([[vOneArray objectAtIndex:i] intValue] > 0) {return kSKOrderedDescending;}}} else if ([vOneArray count] < [vTwoArray count]) {for (NSUInteger i = [vOneArray count]; i < [vTwoArray count]; i++) {if ([[vTwoArray objectAtIndex:i] intValue] > 0) {return kSKOrderedAscending;}}}return kSKOrderedSame;}@end
+(BOOL)doesSystemVersionMeetRequirement:(NSString *)minRequirement{
// eg  NSString *reqSysVer = @"4.0";

NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:minRequirement options:NSNumericSearch] != NSOrderedAscending){return YES;}else{return NO;}

}

Obj-C++11中的一个更通用的版本(您可能可以用NSString/C函数替换其中的一些东西,但这不太冗长。这给了您两种机制。分裂系统版本为您提供了一个所有部分的数组,如果您只想打开主要版本(例如switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }),这很有用。

#include <boost/lexical_cast.hpp>
- (std::vector<int>) splitSystemVersion {std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];std::vector<int> versions;auto i = version.begin();
while (i != version.end()) {auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );std::string versionPart(i, nextIllegalChar);i = std::find_if(nextIllegalChar, version.end(), isdigit);
versions.push_back(boost::lexical_cast<int>(versionPart));}
return versions;}
/** Losslessly parse system version into a number* @return <0>: the version as a number,* @return <1>: how many numeric parts went into the composed number. e.g.* X.Y.Z = 3.  You need this to know how to compare again <0>*/- (std::tuple<int, int>) parseSystemVersion {std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];int versionAsNumber = 0;int nParts = 0;
auto i = version.begin();while (i != version.end()) {auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );std::string versionPart(i, nextIllegalChar);i = std::find_if(nextIllegalChar, version.end(), isdigit);
int part = (boost::lexical_cast<int>(versionPart));versionAsNumber = versionAsNumber * 100 + part;nParts ++;}
return {versionAsNumber, nParts};}

/** Assume that the system version will not go beyond X.Y.Z.W format.* @return The version string.*/- (int) parseSystemVersionAlt {std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];int versionAsNumber = 0;int nParts = 0;
auto i = version.begin();while (i != version.end() && nParts < 4) {auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );std::string versionPart(i, nextIllegalChar);i = std::find_if(nextIllegalChar, version.end(), isdigit);
int part = (boost::lexical_cast<int>(versionPart));versionAsNumber = versionAsNumber * 100 + part;nParts ++;}
// don't forget to pad as systemVersion may have less parts (i.e. X.Y).for (; nParts < 4; nParts++) {versionAsNumber *= 100;}
return versionAsNumber;}

我的解决方案是向您的实用程序类(hint hint)添加一个实用程序方法来解析系统版本并手动补偿浮点数排序。

此外,这段代码相当简单,所以我希望它能帮助一些新手。只需传入一个目标浮点数,并返回一个BOOL。

在你的共享类中像这样声明它:

(+) (BOOL) iOSMeetsOrExceedsVersion:(float)targetVersion;

这样称呼它:

BOOL shouldBranch = [SharedClass iOSMeetsOrExceedsVersion:5.0101];
(+) (BOOL) iOSMeetsOrExceedsVersion:(float)targetVersion {
/*Note: the incoming targetVersion should use 2 digits for each subVersion --
example 5.01 for v5.1, 5.11 for v5.11 (aka subversions above 9), 5.0101 for v5.1.1, etc.*/
// Logic: as a string, system version may have more than 2 segments (example: 5.1.1)// so, a direct conversion to a float may return an invalid number// instead, parse each part directly
NSArray *sysVersion = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];float floatVersion = [[sysVersion objectAtIndex:0] floatValue];if (sysVersion.count > 1) {NSString* subVersion = [sysVersion objectAtIndex:1];if (subVersion.length == 1)floatVersion += ([[sysVersion objectAtIndex:1] floatValue] *0.01);elsefloatVersion += ([[sysVersion objectAtIndex:1] floatValue] *0.10);}if (sysVersion.count > 2) {NSString* subVersion = [sysVersion objectAtIndex:2];if (subVersion.length == 1)floatVersion += ([[sysVersion objectAtIndex:2] floatValue] *0.0001);elsefloatVersion += ([[sysVersion objectAtIndex:2] floatValue] *0.0010);}
if (floatVersion  >= targetVersion)return TRUE;
// elsereturn FALSE;}

使用ios新版本项目(Apache许可证,版本2.0)中包含的版本类,可以轻松获取和比较iOS版本。下面的示例代码转储iOS版本并检查版本是否大于或等于6.0。

// Get the system version of iOS at runtime.NSString *versionString = [[UIDevice currentDevice] systemVersion];
// Convert the version string to a Version instance.Version *version = [Version versionWithString:versionString];
// Dump the major, minor and micro version numbers.NSLog(@"version = [%d, %d, %d]",version.major, version.minor, version.micro);
// Check whether the version is greater than or equal to 6.0.if ([version isGreaterThanOrEqualToMajor:6 minor:0]){// The iOS version is greater than or equal to 6.0.}
// Another way to check whether iOS version is// greater than or equal to 6.0.if (6 <= version.major){// The iOS version is greater than or equal to 6.0.}

项目页面:新版本
Taka hi ko Kawasaki/nv-ios-version

博客:在运行时获取iOS版本并与Version class
进行比较获取并比较运行时iOS版本与Version类

正如苹果官方文档所建议的:您可以使用NSFoundationVersionNumber,来自NSObjCRuntime.h头文件。

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {// here you go with iOS 7}
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {// Your code here}

当然,NSFoundationVersionNumber_iOS_6_1必须更改为适用于您要检查的iOS版本。我现在写的内容可能会在测试设备是否运行iOS7或以前的版本时经常使用。

作为yasimturks解决方案的变体,我定义了一个函数和几个枚举值而不是五个宏。我觉得它更优雅,但这是一个品味问题。

用法:

if (systemVersion(LessThan, @"5.0")) ...

. h文件:

typedef enum {LessThan,LessOrEqual,Equal,GreaterOrEqual,GreaterThan,NotEqual} Comparison;
BOOL systemVersion(Comparison test, NSString* version);

. m文件:

BOOL systemVersion(Comparison test, NSString* version) {NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare: version options: NSNumericSearch];switch (test) {case LessThan:       return result == NSOrderedAscending;case LessOrEqual:    return result != NSOrderedDescending;case Equal:          return result == NSOrderedSame;case GreaterOrEqual: return result != NSOrderedAscending;case GreaterThan:    return result == NSOrderedDescending;case NotEqual:       return result != NSOrderedSame;}}

您应该将应用程序的前缀添加到名称中,尤其是Comparison类型。

所有的答案看起来有点大。我只使用:

if (SYSTEM_VERSION_GREATER_THAN(@"7.0")){(..CODE...)}if (SYSTEM_VERSION_EQUAL_TO(@"7.0")){(..CODE...)}if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")){(..CODE...)}if (SYSTEM_VERSION_LESS_THAN(@"7.0")){(..CODE...)}if (SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(@"7.0")){(..CODE...)}

当然,用您需要的操作系统版本替换@"7.0"

有像7.0或6.0.3这样的版本,所以我们可以简单地将版本转换为数字进行比较。如果版本像7.0,只需将另一个“.0”附加到它,然后获取它的数值。

 int version;NSString* iosVersion=[[UIDevice currentDevice] systemVersion];NSArray* components=[iosVersion componentsSeparatedByString:@"."];if ([components count]==2) {iosVersion=[NSString stringWithFormat:@"%@.0",iosVersion];
}iosVersion=[iosVersion stringByReplacingOccurrencesOfString:@"." withString:@""];version=[iosVersion integerValue];

对于6.0.0

  if (version==600) {// Do something}

为7.0

 if (version==700) {// Do something}

试试下面的代码:

NSString *versionString = [[UIDevice currentDevice] systemVersion];

试试这个

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {// do some work}
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
if (_kisiOS7) {NSLog(@"iOS7 or greater")}else {NSLog(@"Less than iOS7");}

新的方法来检查系统版本使用快速忘记[[UIDevice当前设备]系统版本]和NSFoundationVersionNumber.

我们可以使用NSProcessInfo-isOperatingSystemAtLeastVersion

     import Foundation
let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false

我知道这是一个老问题,但应该有人在Availability.h中提到编译时宏。这里的所有其他方法都是运行时解决方案,在头文件、类类别或ivar定义中不起作用。

对于这些情况,使用

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 && defined(__IPHONE_14_0)// iOS 14+ code here#else// Pre iOS 14 code here#endif

h/t这个答案

派对有点晚,但鉴于iOS8.0,这可能是相关的:

如果你能避免使用

[[UIDevice currentDevice] systemVersion]

相反,检查方法/类/其他任何东西的存在。

if ([self.yourClassInstance respondsToSelector:@selector(<yourMethod>)]){//do stuff}

我发现它对位置管理器很有用,我必须调用iOS8.0的请求WhenInUseAuthorization,但该方法不适用于iOS<8

使用推荐的方式…如果头文件中没有定义,您总是可以让版本使用所需IOS版本的设备在控制台上打印它。

- (BOOL) isIOS8OrAbove{float version802 = 1140.109985;float version8= 1139.100000; // there is no def like NSFoundationVersionNumber_iOS_7_1 for ios 8 yet?NSLog(@"la version actual es [%f]", NSFoundationVersionNumber);if (NSFoundationVersionNumber >= version8){return true;}return false;}

首选方法

在Swift 2.0中,Apple使用更方便的语法添加了可用性检查(阅读更多这里)。现在您可以使用更清晰的语法检查操作系统版本:

if #available(iOS 9, *) {// Then we are on iOS 9} else {// iOS 8 or earlier}

这比检查respondsToSelector etc(Swift中的新功能)更可取。现在,如果您没有正确保护您的代码,编译器将始终警告您。


PreSwift 2.0

iOS8中新增的NSProcessInfo允许更好的语义版本检查。

部署在8iOS及以上

对于iOS8.0或以上的最小部署目标,请使用NSProcessInfooperatingSystemVersionisOperatingSystemAtLeastVersion

这将产生以下结果:

let minimumVersion = NSOperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2)if NSProcessInfo().isOperatingSystemAtLeastVersion(minimumVersion) {//current version is >= (8.1.2)} else {//current version is < (8.1.2)}

部署iOS7

对于iOS7.1或以下的最小部署目标,请使用比较NSStringCompareOptions.NumericSearchUIDevice systemVersion上。

这将产生:

let minimumVersionString = "3.1.3"let versionComparison = UIDevice.currentDevice().systemVersion.compare(minimumVersionString, options: .NumericSearch)switch versionComparison {case .OrderedSame, .OrderedDescending://current version is >= (3.1.3)breakcase .OrderedAscending://current version is < (3.1.3)fallthroughdefault:break;}

更多阅读NSHipster

float deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];float versionToBeCompared = 3.1.3; //(For Example in your case)
if(deviceOSVersion < versionToBeCompared)//Do whatever you need to do. Device version is lesser than 3.1.3(in your case)else//Device version should be either equal to the version you specified or above

实际工作的Swift示例:

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

不要使用NSProcessInfo,因为它在8.0下不起作用,所以在2016年之前几乎没有用

  1. 从主屏幕,点击设置>一般>关于
  2. 您设备的软件版本应显示在此屏幕上。
  3. 检查版本号是否大于3.1.3

我总是把它们保存在我的Constants. h文件中:

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)#define IS_OS_5_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)#define IS_OS_6_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)#define IS_OS_8_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

在Swift中检查iOS版本的解决方案

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

这个解决方案的缺点:检查操作系统版本号是一种糟糕的做法,无论你以哪种方式进行检查。永远不应该以这种方式硬编码依赖关系,总是检查特性、功能或类的存在。考虑一下;苹果可能发布一个类的向后兼容版本,如果他们发布了,那么你建议的代码永远不会使用它,因为你的逻辑寻找操作系统版本号,而不是类的存在。

此信息的来源

Swift中检查类存在的解决方案

if (objc_getClass("UIAlertController") == nil) {// iOS 7} else {// iOS 8+}

不要使用if (NSClassFromString("UIAlertController") == nil),因为它可以在使用iOS7.1和8.2的iOS模拟器上正常工作,但是如果您使用iOS7.1在真实设备上进行测试,您将不幸地注意到您永远不会通过代码片段的其他部分。

#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)

以下是Swift版本:

struct iOSVersion {static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValuestatic let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)}

用法:

if iOSVersion.iOS8 {//Do iOS8 code here}

UI Device+IOS Version. h

@interface UIDevice (IOSVersion)
+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion;+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion;+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion;+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion;+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion
@end

UI Device+IOS Version. m

#import "UIDevice+IOSVersion.h"
@implementation UIDevice (IOSVersion)
+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion{return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedSame;}
+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion{return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedDescending;}
+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion{return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedAscending;}
+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion{return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedAscending;}
+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion{return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedDescending;}
@end

仅用于检索OS版本字符串值:

[[UIDevice currentDevice] systemVersion]

这是yasirmturk宏的Swift版本。希望它能帮助一些人

// MARK: System versionning
func SYSTEM_VERSION_EQUAL_TO(v: String) -> Bool {return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame}
func SYSTEM_VERSION_GREATER_THAN(v: String) -> Bool {return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending}
func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v: String) -> Bool {return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending}
func SYSTEM_VERSION_LESS_THAN(v: String) -> Bool {return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending}
func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v: String) -> Bool {return UIDevice.currentDevice().systemVersion.compare(v, options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending}
let kIsIOS7: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("7")let kIsIOS7_1: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("7.1")let kIsIOS8: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("8")let kIsIOS9: Bool = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("9")

这两个流行的答案存在一些问题:

  1. 使用NSNumericSearch比较字符串有时会产生不直观的结果(SYSTEM_VERSION_*宏都受此影响):

    [@"10.0" compare:@"10" options:NSNumericSearch] // returns NSOrderedDescending instead of NSOrderedSame

    FIX:首先规范化你的字符串,然后执行比较。尝试以相同的格式获取两个字符串可能很烦人。

  2. 检查未来版本时不可能使用基础框架版本符号

    NSFoundationVersionNumber_iOS_6_1 // does not exist in iOS 5 SDK

    FIX:执行两个单独的测试以确保符号存在,然后比较符号。然而这里还有一个:

  3. 基础框架版本符号不是iOS版本所独有的。多个iOS版本可以具有相同的框架版本。

    9.2 & 9.3 are both 1242.128.3 & 8.4 are both 1144.17

    FIX:我认为这个问题无法解决


为了解决这些问题,以下方法将版本号字符串视为10000基数(每个主要/次要/补丁组件都是一个单独的数字),并执行基数转换为十进制以便于使用整数运算符进行比较。

添加了另外两种方法来方便地比较iOS版本字符串和比较具有任意数量组件的字符串。

+ (SInt64)integerFromVersionString:(NSString *)versionString withComponentCount:(NSUInteger)componentCount{//// performs base conversion from a version string to a decimal value. the version string is interpreted as// a base-10000 number, where each component is an individual digit. this makes it simple to use integer// operations for comparing versions. for example (with componentCount = 4):////   version "5.9.22.1" = 5*1000^3 + 9*1000^2 + 22*1000^1 + 1*1000^0 = 5000900220001//    and//   version "6.0.0.0" = 6*1000^3 + 0*1000^2 + 0*1000^1 + 0*1000^1 = 6000000000000//    and//   version "6" = 6*1000^3 + 0*1000^2 + 0*1000^1 + 0*1000^1 = 6000000000000//// then the integer comparisons hold true as you would expect:////   "5.9.22.1" < "6.0.0.0" // true//   "6.0.0.0" == "6"       // true//
static NSCharacterSet *nonDecimalDigitCharacter;static dispatch_once_t onceToken;dispatch_once(&onceToken,^{  // don't allocate this charset every time the function is callednonDecimalDigitCharacter = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];});
SInt64 base    = 10000; // each component in the version string must be less than baseSInt64 result  =     0;SInt64 power   =     0;
// construct the decimal value left-to-right from the version stringfor (NSString *component in [versionString componentsSeparatedByString:@"."]){if (NSNotFound != [component rangeOfCharacterFromSet:nonDecimalDigitCharacter].location){// one of the version components is not an integer, so bail outresult = -1;break;}result += [component longLongValue] * (long long)pow((double)base, (double)(componentCount - ++power));}
return result;}
+ (SInt64)integerFromVersionString:(NSString *)versionString{return [[self class] integerFromVersionString:versionStringwithComponentCount:[[versionString componentsSeparatedByString:@"."] count]];}
+ (SInt64)integerFromiOSVersionString:(NSString *)versionString{// iOS uses 3-component version stringreturn [[self class] integerFromVersionString:versionStringwithComponentCount:3];}

它有点面向未来,因为它支持许多修订标识符(通过4位数字,0-9999;更改base以调整此范围)并且可以支持任意数量的组件(Apple现在似乎使用3个组件,例如major.minor.patch),但这可以使用componentCount参数显式指定。确保您的componentCountbase不会导致溢出,即确保2^63 >= base^componentCount

使用示例:

NSString *currentVersion = [[UIDevice currentDevice] systemVersion];if ([Util integerFromiOSVersionString:currentVersion] >= [Util integerFromiOSVersionString:@"42"]){NSLog(@"we are in some horrible distant future where iOS still exists");}
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

然后添加一个if条件如下:-

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {//Your code}

从Xcode 9开始,在Objective-c中:

if (@available(iOS 11, *)) {// iOS 11 (or newer) ObjC code} else {// iOS 10 or older code}

从Xcode 7开始,在Swift中:

if #available(iOS 11, *) {// iOS 11 (or newer) Swift code} else {// iOS 10 or older code}

对于版本,您可以指定MAJOR、MINOR或PATCH(有关定义,请参阅http://semver.org/)。例子:

  • iOS 11iOS 11.0是同一个最小版本
  • iOS 10iOS 10.3iOS 10.3.1是不同的最小版本

您可以为任何这些系统输入值:

  • iOSmacOSwatchOStvOS

真实案例取自我的一个豆荚

if #available(iOS 10.0, tvOS 10.0, *) {// iOS 10+ and tvOS 10+ Swift code} else {// iOS 9 and tvOS 9 older code}

留档

在您的项目中添加下面的Swift代码,并轻松访问iOS版本和设备等信息。

class DeviceInfo: NSObject {
struct ScreenSize{static let SCREEN_WIDTH = UIScreen.main.bounds.size.widthstatic let SCREEN_HEIGHT = UIScreen.main.bounds.size.heightstatic let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)}
struct DeviceType{static let IS_IPHONE_4_OR_LESS =  UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH >= 667.0static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0static let IS_IPAD      = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0static let IS_IPAD_PRO  = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1366.0}
struct VersionType{static let SYS_VERSION_FLOAT = (UIDevice.current.systemVersion as NSString).floatValuestatic let iOS7 = (VersionType.SYS_VERSION_FLOAT < 8.0 && VersionType.SYS_VERSION_FLOAT >= 7.0)static let iOS8 = (VersionType.SYS_VERSION_FLOAT >= 8.0 && VersionType.SYS_VERSION_FLOAT < 9.0)static let iOS9 = (VersionType.SYS_VERSION_FLOAT >= 9.0 && VersionType.SYS_VERSION_FLOAT < 10.0)static let iOS10 = (VersionType.SYS_VERSION_FLOAT >= 9.0 && VersionType.SYS_VERSION_FLOAT < 11.0)}}

基本上与这个https://stackoverflow.com/a/19903595/1937908相同,但更健壮:

#ifndef func_i_system_version_field#define func_i_system_version_field
inline static int i_system_version_field(unsigned int fieldIndex) {NSString* const versionString = UIDevice.currentDevice.systemVersion;NSArray<NSString*>* const versionFields = [versionString componentsSeparatedByString:@"."];if (fieldIndex < versionFields.count) {NSString* const field = versionFields[fieldIndex];return field.intValue;}NSLog(@"[WARNING] i_system_version(%iu): field index not present in version string '%@'.", fieldIndex, versionString);return -1; // error indicator}
#endif

只需将上述代码放在头文件中。

用法:

int major = i_system_version_field(0);int minor = i_system_version_field(1);int patch = i_system_version_field(2);