如何检查iOS版本?

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

 [[UIDevice currentDevice].systemVersion floatValue] 

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

 if (version > 3.1.3) { } 

我怎样才能做到这一点?

快速回答…

从Swift 2.0开始,您可以使用#availableguard来保护只能在特定系统上运行的代码。

if #available(iOS 9, *) {}

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

iOS 8及以上版本的[[NSProcessInfo processInfo] operatingSystemVersion]

从Xcode 9开始:

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

完整的答案…

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

检查是否存在API:

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

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

对于弱连接的类,直接向类发送消息是安全的。 值得注意的是,这适用于没有明确链接为“必需”的框架。 对于缺less的类,expression式评估为零,失败的条件:

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

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

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

检查是否存在符号:

偶尔,你必须检查常量的存在。 这在iOS 8中引入了UIApplicationOpenSettingsURLString ,用于通过-openURL:加载设置应用程序。 该值在iOS 8之前不存在。将nil传递给此API将会崩溃,因此您必须首先确认常量是否存在:

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

与操作系统版本比较:

假设您正面临着检查操作系统版本的相对罕见的需求。 对于定位iOS 8及更高版本的项目, NSProcessInfo包含一个用于执行版本比较的方法,其出错几率较低:

 - (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version 

针对旧系统的项目可以使用systemVersion上的systemVersion 。 苹果公司在他们的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是你想要的,那么一定要把它当作一个string来处理,否则你可能会截断补丁版本号(比如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")) { ... } 

正如苹果官方文档所build议的那样:您可以使用NSObjCRuntime.h头文件中的NSObjCRuntime.h

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

尝试:

 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中,Apple增加了可用性检查,使用更简便的语法(请阅读此处 )。 现在你可以使用更清晰的语法来检查操作系统版本:

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

这是优先检查respondsToSelector等( 什么是新的在Swift中 )。 现在如果你没有正确地守护你的代码,编译器会一直提醒你。


Pre Swift 2.0

iOS 8中的新function是NSProcessInfo允许更好的语义版本检查。

在iOS 8和更高版本上部署

对于iOS 8.0或更高版本的最低部署目标,请使用NSProcessInfo operatingSystemVersionisOperatingSystemAtLeastVersion

这将产生以下结果:

 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) } 

在iOS 7上部署

对于iOS 7.1或更低版本的最低部署目标,请使用与UIDevice systemVersion上的NSStringCompareOptions.NumericSearch进行比较。

这将产生:

 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) break case .OrderedAscending: //current version is < (3.1.3) fallthrough default: break; } 

更多阅读NSHipster 。

这用于在Xcode中检查兼容的SDK版本,这是如果您有一个拥有不同版本的Xcode的大型团队或支持不同SDK的多个项目共享相同的代码:

 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 //programming in iOS 8+ SDK here #else //programming in lower than iOS 8 here #endif 

你真正想要的是检查设备上的iOS版本。 你可以这样做:

 if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) { //older than iOS 8 code here } else { //iOS 8 specific code here } 

Swift版本:

 if let version = Float(UIDevice.current.systemVersion), version < 9.3 { //add lower than 9.3 code here } else { //add 9.3 and above code here } 

Objective-C中启动Xcode 9:

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

Swift中启动Xcode 7:

 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是不同的最低版本

您可以input任何这些系统的值:

  • iOSmacOSwatchOStvOS

从我的豆荚中抽取的真实案例:

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

文件

我build议:

 if ([[[UIDevice currentDevice] systemVersion] floatValue] > 3.13) { ; // ... } 

信用: 如何针对特定的iPhone版本?

我总是把这些保存在我的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) 
 +(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; } } 

使用nv-ios-version项目(Apache许可证2.0版)中包含的Version类,可以轻松获取和比较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. } 

项目页面: nv-ios-version
TakahikoKawasaki / NV-IOS版本

博客:在运行时使用Version类获取并比较iOS版本
在运行时获取和比较iOS版本和Version类

使用swift Forget [[UIDevice currentDevice] systemVersion]和NSFoundationVersionNumber检查系统版本的新方法。

我们可以使用NSProcessInfo -isOperatingSystemAtLeastVersion

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

的UIDevice + IOSVersion.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 

的UIDevice + IOSVersion.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 

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

当这不是一个选项,你需要在这里小心,因为[@"5.0" compare:@"5" options:NSNumericSearch]返回NSOrderedDescending这可能根本不是有意的; 我可能期望NSOrderedSame在这里。 这至less是理论上的问题,我认为值得捍卫。

另外值得考虑的是不能合理比较的不好的版本input的可能性。 苹果提供了三个预定义的常量NSOrderedAscendingNSOrderedSameNSOrderedDescending但我可以想象一个名为NSOrderedUnordered的事件,我不能比较两件事情,我想返回一个值,指示这一点。

更重要的是,苹果有一天会扩展它们的三个预定义的常量来允许各种返回值并不是不可能的,从而做出比较!= 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 
 if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) { // Your code here } 

当然, NSFoundationVersionNumber_iOS_6_1必须更改为适用于您要检查的iOS版本。 我现在写的东西在testing设备是运行iOS7还是以前的版本时可能会用到很多。

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

有点晚了党,但从iOS 8.0的angular度来看,这可能是相关的:

如果你能避免使用

[[UIDevice currentDevice] systemVersion]

相反,检查一个方法/类/其他的存在。

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

我发现它对位置pipe理器非常有用,我必须调用requestWhenInUseAuthorization for iOS 8.0,但该方法不适用于iOS <8

有像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]; 

仅用于检索操作系统版本string值:

 [[UIDevice currentDevice] systemVersion] 
 #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 } 

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

用法:

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

您应该将您的应用程序的前缀添加到名称,特别是Comparisontypes。

我知道这是一个老问题,但有人应该提到了Availability.h中的编译时macros。 这里的所有其他方法都是运行时解决scheme,不能用于头文件,类别类别或伊维尔定义。

对于这些情况,请使用

 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_6_0 // iOS 6+ code here #else // Pre iOS 6 code here #endif 

h / t 这个答案

使用推荐的推荐方式…如果在头文件中没有定义,您可以随时使用所需的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; } 
 #define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) 

Obj-C ++ 11中的一个更通用的版本(你也许可以用NSString / C函数replace一些这样的东西,但是这并不是那么冗长,这给了你两种机制:splitSystemVersion为你提供了一个有用的所有部分的数组if你只想打开主版本(例如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. eg * XYZ = 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 XYZW 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 (ie XY). for (; nParts < 4; nParts++) { versionAsNumber *= 100; } return versionAsNumber; } 

尝试这个

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { // do some work } 
 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年之前它几乎没有任何用处

在Swift中检查iOS版本的解决scheme

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

这个解决scheme的概念:检查操作系统版本号,无论采用哪种方式,都是不好的做法。 一个人不应该以这种方式硬编码依赖关系,总是检查function,能力或类的存在。 考虑这个; 苹果可能会发布一个向后兼容的类,如果他们这样做,那么你build议的代码将永远不会使用它,因为你的逻辑查找操作系统的版本号,而不是类的存在。

( 这个信息的来源 )

在Swift中检查类的存在的解决scheme

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

不要使用if (NSClassFromString("UIAlertController") == nil)因为它可以在使用iOS 7.1和8.2的iOS模拟器上正常工作,但是如果你在使用iOS 7.1的真实设备上testing,你将不会注意到,通过代码片段的其他部分。