如何查看iOS版本?

How to check iOS version?

提问人:John 提问时间:7/27/2010 最后编辑:James WebsterJohn 更新时间:11/15/2023 访问量:529454

问:

我想检查设备的版本是否比我尝试过的版本大:iOS3.1.3

[[UIDevice currentDevice].systemVersion floatValue]

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

if (version > 3.1.3) { }

我怎样才能做到这一点?

IOS的 Objective-C

评论

7赞 Matt 8/7/2015
主持人注:随着时间的流逝,这个问题已经累积了 30 多个答案。在添加新答案之前,请确保尚未提供解决方案。
5赞 Cœur 6/8/2017
在 Swift 中启动 Xcode 7。在 objective-c 中启动 Xcode 9。if #available(iOS 9, *) {}if (@available(iOS 11, *)) {}

答:

39赞 Jonathan Grynspan 7/27/2010 #1

尝试:

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
}

评论

2赞 Rob 5/13/2012
为什么不颠倒这里的顺序并保存比较,因为@“3.1.3”和 systemVersion 都是 NSStrings?ie: ' if ([@“3.1.3” compare: [UIDevice currentDevice].systemVersion options: NSNumericSearch] == NSOrderedDescending) ;// 操作系统版本 >= 3.1.3 else ;// 操作系统版本 < 3.1.3'
3赞 Jonathan Grynspan 5/13/2012
这样做可能会使逻辑不那么清晰。但是,该操作应该是等效的。
1赞 KPM 7/30/2012
两个整数之间的比较肯定不是很昂贵。
0赞 Jonathan Grynspan 7/30/2012
这真的是一个风格问题。消息发送的开销将大大超过额外的整数比较。
1050赞 Justin 7/27/2010 #2

快速回答......


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

if #available(iOS 9, *) {}


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

[[NSProcessInfo processInfo] operatingSystemVersion]在 iOS 8 及更高版本中。

从 Xcode 9 开始:

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


完整的答案......

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

检查是否存在 API:

例如,您可以使用以下命令检查当前设备上是否可用:UIPopoverControllerNSClassFromString

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

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

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

某些类(如 和)提供了检查设备功能的方法:CLLocationManagerUIDevice

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

检查是否存在符号:

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

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

与操作系统版本比较:

假设您面临着相对罕见的检查操作系统版本的需求。对于面向 iOS 8 及更高版本的项目,包括一种执行版本比较的方法,出错几率较小:NSProcessInfo

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

面向旧系统的项目可以在 上使用。Apple 在其 GLSprite 示例代码中使用它。systemVersionUIDevice

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

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

评论

162赞 Brad Larson 7/27/2010
在某些特定情况下,需要检查系统版本。例如,在 3.x 中私有的几个类和方法在 4.0 中被公开,因此,如果您只是检查它们的可用性,则会在 3.x 中得到错误的结果。此外,UIScrollViews 处理缩放比例的方式在 3.2 及更高版本中发生了细微变化,因此您需要检查操作系统版本才能正确处理结果。
2赞 jww 7/17/2011
iOS 3.2 似乎没有发送 .我的技巧是确定是否< iOS 4.0,并在根视图的 .-viewWillAppearUISplitViewController-didSelectRowAtIndexPath
10赞 Ken 12/10/2011
您在这里需要小心一点,因为 返回 ,这很可能根本不是故意的。(我可能会期待。这至少是一种理论上的可能性。[@"10.0" compare:@"10" options:NSNumericSearch]NSOrderedDescendingNSOrderedSame
0赞 Hot Licks 3/16/2013
是的,我刚刚遇到了一个需要规避 iOS 5 错误的情况。 等人不会做这项工作 - 必须比较版本。respondsToSelector
2赞 rckoenes 11/3/2015
随着 TVos 的引入,这一点变得更加重要。请参阅 TVos 将在使用 9.1 SDK 时返回 9.0。因此,检查类或方法(选择器)是最好的方法,在此之后,您应该检查NSFoundationVersionNumber,只有在不可能的情况下,才应检查系统版本。UIDevice
1061赞 yasirmturk #3
/*
 *  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")) {
    ...
}

评论

20赞 Rab 12/12/2011
+1.将其保存在标题中,您可以将其包含在需要的地方是我能想到的最简单的解决方案。在某些情况下,这比使用 NSClassFromString 检查可用性更可靠。另一个示例是在 iAd 中,如果在 4.2 之前的版本中使用 ADBannerContentSizeIdentifierPortrait,则将获得 EXEC_BAD_ACCESS,但在 4.1 之后,等效的 ADBannerContentSizeIdentifier320x50 将被弃用。
1赞 Paul de Lange 11/20/2012
我使用它的另一个地方是使用 UIPageViewController 并在 iOS6 中将样式设置为 UIPageViewControllerTransitionStyleScroll。
8赞 pzulw 7/12/2013
这在 10 秒内不起作用。例如,比较 4.10 和 4.9 会给出错误的结果。
9赞 Yan 9/24/2013
使用可选数字时应非常小心。例如,在 iOS 7.0 上给出不正确的结果。.0SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")
1赞 whyoz 10/15/2013
我刚刚测试过将其放入我的 .pch 文件中,效果很好(至少使用 Xcode 5 构建)
3赞 Ken 12/10/2011 #4

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

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

同样值得考虑的是,无法合理地与之进行比较的错误版本输入的可能性。Apple 提供了三个预定义的常量,但是如果我不能比较两个东西并且我想返回一个指示这一点的值,我可以想到一些东西的用途。NSOrderedAscendingNSOrderedSameNSOrderedDescendingNSOrderedUnordered

更重要的是,苹果有朝一日会扩展他们的三个预定义常量,以允许各种返回值,这使得比较变得不明智,这并非不可能。!= 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
6赞 Jef 11/20/2012 #5
+(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;
  }


}

评论

0赞 Andres Canella 7/8/2015
@Jef 句点不是版本控制中的小数点,而是相关的。你的答案不会忽略句点,如果忽略,它会失败。在版本控制中,每个句点分隔的元素都是一个完整的数字。例如:“1.23.45”大于“1.2.345”,因为第二个元素“23”大于“2”。如果您要消除句点,它将是相同的数字。
0赞 Vitali 11/30/2012 #6

Obj-C++ 11 中更通用的版本(你可以用 NSString/C 函数替换其中的一些内容,但这不那么冗长。这为您提供了两种机制。splitSystemVersion 为您提供了一个包含所有部分的数组,如果您只想打开主要版本(例如)。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;
}
-1赞 eGanges 1/11/2013 #7

我的解决方案是将实用程序方法添加到实用程序类(提示提示)中,以解析系统版本并手动补偿浮点数排序。

此外,这段代码相当简单,所以我希望它对一些新手有所帮助。只需传入目标浮点数,然后返回 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);
    else
        floatVersion += ([[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);
    else
        floatVersion += ([[sysVersion objectAtIndex:2] floatValue] *0.0010);
}

if (floatVersion  >= targetVersion) 
    return TRUE;

// else
return FALSE;
 }
6赞 Takahiko Kawasaki 4/3/2013 #8

使用 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

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

252赞 CarlJ 8/6/2013 #9

正如官方 Apple 文档所建议的那样:您可以使用头文件中的 NSFoundationVersionNumberNSObjCRuntime.h

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

评论

41赞 mxcl 9/12/2013
+1 这实际上是这里最安全、准确的选择。
8赞 Kjuly 9/22/2013
嗯。.在 iOS 5 SDK 中不存在。NSFoundationVersionNumber_iOS_6_1
2赞 CarlJ 9/24/2013
@Kjuly您可以自己定义缺少的版本号: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h(查看第 102-130 行)
3赞 Cœur 10/2/2013
不,你错了,NSFoundationVersionNumber_iOS_7_0不存在。但是,我们可以用 来定义它。为了避免这样一团糟,我使用了 yasirmturk 的 SYSTEM_VERSION_LESS_THAN(v) 宏#ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif
8赞 CarlJ 9/19/2014
不,但 Apple 将在 iOS 9 中添加。只需检查NSFoundationVersionNumber_iOS_8_0NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
4赞 OscarWyck 10/4/2013 #10
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

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

1赞 jcsahnwaldt Reinstate Monica 10/8/2013 #11

作为 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

-4赞 Msmit1993 10/17/2013 #12

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

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"

评论

0赞 Andres Canella 7/8/2015
这并不能回答任何问题。
0赞 HelloGoodbye 1/20/2016
@AndresCanella我想答案是,所以它确实回答了这个问题,不是吗?if (SYSTEM_VERSION_GREATER_THAN(@"7.0")){(..CODE...)}
0赞 Andres Canella 1/21/2016
@HelloGoodbye 不,这并不能回答主题问题。它不明确地建议使用定义,但它不包括定义的实际代码。例如:答案应与主题问题直接相关,并且应清晰。这就是为什么它被否决了。#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
2赞 NaXir 11/11/2013 #13

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

评论

0赞 ardnew 1/27/2017
简单地删除小数点是错误的方法。考虑长度超过 1 个字符的组件,例如 .那么这个算法将产生 ,这是不正确的。6.1.106110 > 700
0赞 NaXir 1/27/2017
我知道苹果在推出新版本方面很糟糕,但在大多数时候,版本的第二个数字从未超过 5,所以 10 是不可能的。这是一种临时方法,因此,如果它处理 2 个组件的大小写,如果您想手动处理,您可以将其修改为处理 4 个大小写。无论如何,这种方法在 iOS6 或 7 时被评论过。iOS 9 和 10 有更好的检查方法,即 #available。
2赞 annu 3/23/2014 #14

请尝试以下代码:

NSString *versionString = [[UIDevice currentDevice] systemVersion];
0赞 Muhammad Aamir Ali 4/3/2014 #15

试试这个

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { 
// do some work
}

评论

0赞 Kevin Panko 4/3/2014
解释一下这是做什么的。
0赞 Muhammad Aamir Ali 4/3/2014
如果会检查操作系统版本是否为 iOS 7
3赞 Gaurav Gilani 5/17/2014 #16
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

if (_kisiOS7) {
            NSLog(@"iOS7 or greater")
} 
else {
           NSLog(@"Less than iOS7");
}
4赞 Govind 6/11/2014 #17

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

我们可以使用 NSProcessInfo -isOperatingSystemAtLeastVersion

     import Foundation

     let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
     NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
6赞 bcattle 9/18/2014 #18

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

对于这些情况,请使用

#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 这个答案

4赞 Denis Kanygin 9/24/2014 #19

派对有点晚了,但鉴于 iOS 8.0 的存在,这可能是相关的:

如果可以避免使用

[[UIDevice currentDevice] systemVersion]

相反,请检查是否存在方法/类/任何其他内容。

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

我发现它对位置管理器很有用,我必须为 iOS 8.0 调用 requestWhenInUseAuthorization,但该方法不适用于 iOS < 8

1赞 tyoc213 10/2/2014 #20

使用推荐的推荐方式...如果头文件中没有定义,则始终可以使用所需IOS versión的设备在控制台上打印版本。

- (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;
}
35赞 Daniel Galasko 10/7/2014 #21

首选方法

在 Swift 2.0 中,Apple 使用更方便的语法添加了可用性检查(在此处阅读更多内容)。现在,您可以使用更简洁的语法检查操作系统版本:

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

这是检查等的首选(Swift 中的新功能)。现在,如果你没有正确保护你的代码,编译器将始终警告你。respondsToSelector


Swift 2.0 之前的版本

iOS 8 的新功能允许更好的语义版本控制检查。NSProcessInfo

在 iOS 8 及更高版本上部署

对于 iOS 8.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)
}

在 iOS 7 上部署

对于 iOS 7.1 或更低版本的最低部署目标,请使用 compare with on 。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)
        break
    case .OrderedAscending:
        //current version is < (3.1.3)
        fallthrough
    default:
        break;
}

NSHipster的更多阅读。

0赞 GJDK 11/12/2014 #22
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

评论

0赞 Pang 8/9/2016
float versionToBeCompared = 3.1.3;甚至无法编译。
0赞 Esqarrouth 12/8/2014 #23

实际有效的 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 年它几乎没用

-5赞 HelloGoodbye 1/9/2015 #24
  1. 在主屏幕中,点击“设置”>“常规”>“关于”。
  2. 您设备的软件版本应显示在此屏幕上。
  3. 检查版本号是否大于 。3.1.3

评论

0赞 HelloGoodbye 8/30/2015
对我的答案投反对票的人能否也提供他们这样做的动机?那将很有帮助。
0赞 ecnepsnai 10/1/2015
你被否决了,因为你的答案不适合这个网站。问题是如何使用代码检查设备版本,而不是如何检查设备上的设置的分步操作。您的答案将更适合 Ask Different。
0赞 HelloGoodbye 1/20/2016
@ecnepsnai 但我的意思是,如果这是一个编程问题,至少说出你使用的是什么编程语言不是很有意义吗?
9赞 Segev 3/15/2015 #25

我总是把它们保存在我的 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)

评论

0赞 Vaibhav Jhaveri 4/3/2015
伟大。最好将其放在 XCode 项目的文件中.pch
1赞 Segev 4/3/2015
我将所有常量放在导入到文件中的文件中。Constants.hpch
1赞 King-Wizard 3/20/2015 #26

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

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

(此信息的来源)

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

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

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

评论

0赞 King-Wizard 4/6/2015
为什么要投反对票?该解决方案可在 Swift 和任何 iOS 版本上完美运行。尤其是对类存在的检查,简直完美。
1赞 Gank 5/30/2015 #27
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
0赞 Swinny89 7/23/2015 #28

这是一个 swift 版本:

struct iOSVersion {
    static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue
    static 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
}

评论

0赞 Kastor 9/19/2016
我认为版本应该是第 3-6 行的 iOSVersion,例如struct iOSVersion { static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue static let iOS7 = (iOSVersion.SYS_VERSION_FLOAT < 8.0 && iOSVersion.SYS_VERSION_FLOAT >= 7.0) static let iOS8 = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0) static let iOS9 = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0) }
4赞 Oliver Pearmain 8/7/2015 #29

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
4赞 Javier Calatrava Llavería 8/10/2015 #30

仅用于检索操作系统版本字符串值:

[[UIDevice currentDevice] systemVersion]
0赞 Beninho85 1/20/2016 #31

这是 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赞 ardnew 1/27/2017 #32

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

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

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

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

  2. 在检查将来的发行版时,无法使用 foundation framework 版本符号

    NSFoundationVersionNumber_iOS_6_1 // does not exist in iOS 5 SDK
    

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

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

    9.2 & 9.3 are both 1242.12
    8.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 called
            nonDecimalDigitCharacter = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
        });

    SInt64 base    = 10000; // each component in the version string must be less than base
    SInt64 result  =     0;
    SInt64 power   =     0;

    // construct the decimal value left-to-right from the version string
    for (NSString *component in [versionString componentsSeparatedByString:@"."])
    {
        if (NSNotFound != [component rangeOfCharacterFromSet:nonDecimalDigitCharacter].location)
        {
            // one of the version components is not an integer, so bail out
            result = -1;
            break;
        }
        result += [component longLongValue] * (long long)pow((double)base, (double)(componentCount - ++power));
    }

    return result;
}

+ (SInt64)integerFromVersionString:(NSString *)versionString
{
    return [[self class] integerFromVersionString:versionString
                               withComponentCount:[[versionString componentsSeparatedByString:@"."] count]];
}

+ (SInt64)integerFromiOSVersionString:(NSString *)versionString
{
    // iOS uses 3-component version string
    return [[self class] integerFromVersionString:versionString
                               withComponentCount:3];
}

它在某种程度上是面向未来的,因为它支持许多修订标识符(通过 4 位数字,0-9999;更改以调整此范围)并且可以支持任意数量的组件(Apple 现在似乎使用 3 个组件,例如),但这可以使用参数显式指定。确保你的并且不造成溢出,即确保!basemajor.minor.patchcomponentCountcomponentCountbase2^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");
}
3赞 Sumit Kumar Saha 2/8/2017 #33
#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
}       
139赞 Cœur 6/8/2017 #34

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 11并且是相同的最小版本iOS 11.0
  • iOS 10、 是不同的最小版本iOS 10.3iOS 10.3.1

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

  • iOS, , , , , ...(见文档)macOSwatchOStvOSvisionOS

我的一个 pod 中获取的真实案例:

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

可用的文档

评论

0赞 Legoless 9/19/2017
在 Objective-C 或 Swift 中,这怎么能颠倒过来?
0赞 Cœur 9/19/2017
@Legolessif (...) {} else { ... }
0赞 Legoless 9/19/2017
我可以在 Objective-C 中使用而不是在语句中保持块打开和缩进吗?guardelse
0赞 Cœur 9/19/2017
@Legoless不,只需使用一个空块,后跟一个 .ifelse
1赞 Legoless 9/19/2017
这就是我目前拥有的解决方案,只是想避免不必要的缩进和空块。if
-1赞 Kiran K 4/17/2018 #35

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

class DeviceInfo: NSObject {

    struct ScreenSize
    {
        static let SCREEN_WIDTH = UIScreen.main.bounds.size.width
        static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
        static 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.0
        static let IS_IPHONE_5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
        static let IS_IPHONE_6 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH >= 667.0
        static let IS_IPHONE_6P = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
        static let IS_IPHONE_X = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
        static let IS_IPAD      = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
        static 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).floatValue
        static 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)
    }
}
0赞 Anticro 1/31/2020 #36

与这个想法基本相同,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);