【问题标题】:How to check iOS version?如何查看iOS版本?
【发布时间】:2011-03-21 08:43:10
【问题描述】:

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

[[UIDevice currentDevice].systemVersion floatValue]

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

if (version > 3.1.3) { }

我怎样才能做到这一点?

【问题讨论】:

  • 版主注意:随着时间的推移,这个问题已经积累了 30 多个答案。在添加新答案之前,请确保您的解决方案尚未提供。
  • 在 Swift 中启动 Xcode 7,if #available(iOS 9, *) {}。在 Objective-c 中启动 Xcode 9,if (@available(iOS 11, *)) {}

标签: ios objective-c


【解决方案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
}

【讨论】:

  • 既然@"3.1.3" 和systemVersion 都是NSStrings,为什么不在这里颠倒顺序并保存比较呢?即:` if ([@"3.1.3" compare: [UIDevice currentDevice].systemVersion options: NSNumericSearch] == NSOrderedDescending) ;// 操作系统版本 >= 3.1.3 else ;// 操作系统版本
  • 这样做可能会使逻辑不太清晰。但是,操作应该是等效的。
  • 两个整数之间的比较肯定不会很昂贵。
  • 这真的是风格问题。消息分发的开销将大大超过额外的整数比较。
【解决方案2】:

快速回答……


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

if #available(iOS 9, *) {}


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

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

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

检查符号是否存在:

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

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

与操作系统版本比较:

假设您面临着检查操作系统版本的相对罕见的需求。对于面向 iOS 8 及更高版本的项目,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)。

【讨论】:

  • 在特定情况下需要检查系统版本。例如,一些在 3.x 中私有的类和方法在 4.0 中被公开,因此如果您只是检查它们的可用性,您将在 3.x 中得到错误的结果。此外,UIScrollViews 处理缩放比例的方式在 3.2 及更高版本中发生了微妙的变化,因此您需要检查操作系统版本才能正确处理结果。
  • iOS 3.2 似乎没有在UISplitViewController 中发送-viewWillAppear。我的 hack 是确定是否 -didSelectRowAtIndexPath 中将其发送到详细视图控制器。
  • 这里需要小心一点,因为[@"10.0" compare:@"10" options:NSNumericSearch] 返回NSOrderedDescending,这很可能根本不是故意的。 (我可能期待NSOrderedSame。)这至少是理论上的可能性。
  • 是的,我刚刚遇到了一个需要绕过 iOS 5 错误的案例。 respondsToSelector 等人不会做这项工作——必须比较版本。
  • 随着 TVos 的推出,这一点变得更加重要。当使用 9.1 SDK 时,请参阅 TVos 将返回 9.0。所以检查类或方法(选择器)是最好的方法,之后你应该检查NSFoundationVersionNumber,只有在不可能的情况下,你才应该检查UIDevice上的系统版本。
【解决方案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")) {
    ...
}

【讨论】:

  • +1。将其保存在您可以在需要的地方包含的标题中是我能想到的最简单的解决方案。在某些情况下,这比使用 NSClassFromString 检查可用性更可靠。另一个例子是在 iAd 中,如果您在 4.2 之前的版本中使用 ADBannerContentSizeIdentifierPortrait,您将获得 EXEC_BAD_ACCESS,但在 4.1 之后不推荐使用等效的 ADBannerContentSizeIdentifier320x50。
  • 我使用它的另一个地方是 UIPageViewController 并在 iOS6 中将样式设置为 UIPageViewControllerTransitionStyleScroll。
  • 这在 10 秒内不起作用。例如比较 4.10 和 4.9 会得到错误的结果。
  • 在使用可选的.0 数字时应该非常小心。例如SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0") 在 iOS 7.0 上给出的结果不正确。
  • 我刚刚测试了将其放入我的 .pch 文件中,效果很好(至少使用 Xcode 5 构建)
【解决方案4】:

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

当这不是一个选项时,你确实需要小心一点,因为[@"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

【讨论】:

    【解决方案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;
      }
    
    
    }
    

    【讨论】:

    • @Jef 句点在版本控制中不是小数点并且是相关的。您的答案不会忽略句点,如果这样做会失败。在版本控制中,每个句点分隔的元素都是一个完整的数字。例如:“1.23.45”大于“1.2.345”,因为第二个元素“23”大于“2”。如果你要消除句号,那将是相同的数字。
    【解决方案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;
    }
    

    【讨论】:

      【解决方案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;
       }
      

      【讨论】:

        【解决方案8】:

        使用nv-ios-version项目(Apache License,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 版本并将其与 Version 类进行比较
        Get and compare iOS version at runtime with Version class

        【讨论】:

          【解决方案9】:

          根据official Apple docs 的建议:您可以使用NSObjCRuntime.h 头文件中的NSFoundationVersionNumber

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

          【讨论】:

          • +1 这实际上是这里最安全和最准确的选项。
          • Um..NSFoundationVersionNumber_iOS_6_1 在 iOS 5 SDK 中不存在。
          • @Kjuly 您可以自己定义缺少的版本号:github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h(查看第 102-130 行)
          • 不,你错了,NSFoundationVersionNumber_iOS_7_0 不存在。但是,我们可以用#ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif 定义它。为了避免这样的混乱,我使用了 yasirmturk 的 SYSTEM_VERSION_LESS_THAN(v) 宏
          • 不,但苹果会在 iOS 9 中添加NSFoundationVersionNumber_iOS_8_0。只需检查NSFoundationVersionNumber &gt; NSFoundationVersionNumber_iOS_7_1
          【解决方案10】:
          if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
                  // Your code here
          }
          

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

          【讨论】:

            【解决方案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 类型。

            【讨论】:

              【解决方案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" 替换为您所需的操作系统版本。

              【讨论】:

              • 这不回答任何问题。
              • @AndresCanella 我猜答案是if (SYSTEM_VERSION_GREATER_THAN(@"7.0")){(..CODE...)},所以它确实回答了这个问题,不是吗?
              • @HelloGoodbye 不,这不回答主题问题。它不明确地建议使用定义,但它不包括定义的实际代码。例如:#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 答案应该与主题问题直接相关并且应该清楚。这就是为什么这被否决了。
              【解决方案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
               }
              

              【讨论】:

              • 简单地删除小数点是错误的方法。考虑一个长度超过 1 个字符的组件,例如6.1.10。那么这个算法将产生6110 &gt; 700,这是不正确的。
              • 我知道苹果不擅长推出新版本,但大多数时候版本的第二个数字从未超过 5,所以 10 是毫无疑问的。这是一种临时方法,因此如果它处理 2 个组件的案例,如果您想手动执行,您可以修改它以处理四个案例。无论如何,这种方法在 iOS6 或 7 时已被评论。iOS 9 和 10 有更好的检查方法,即 #available。
              【解决方案14】:

              试试下面的代码:

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

              【讨论】:

                【解决方案15】:

                试试这个

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

                【讨论】:

                • 解释一下这是做什么的。
                • if会检查操作系统版本是否为ios 7
                【解决方案16】:
                #define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
                
                if (_kisiOS7) {
                            NSLog(@"iOS7 or greater")
                } 
                else {
                           NSLog(@"Less than iOS7");
                }
                

                【讨论】:

                  【解决方案17】:

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

                  我们可以使用 NSProcessInfo -isOperatingSystemAtLeastVersion

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

                  【讨论】:

                    【解决方案18】:

                    我知道这是一个老问题,但应该有人在 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 this 回答

                    【讨论】:

                      【解决方案19】:

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

                      如果你可以避免使用

                      [[UIDevice currentDevice] systemVersion]

                      而是检查是否存在方法/类/其他任何东西。

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

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

                      【讨论】:

                        【解决方案20】:

                        使用参考推荐的方式...如果头文件中没有定义,您始终可以使用所需 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;
                        }
                        

                        【讨论】:

                          【解决方案21】:

                          首选方法

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

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

                          这是检查respondsToSelector 等(What's New In Swift)的首选。现在,如果您没有正确保护您的代码,编译器将始终警告您。


                          前 Swift 2.0

                          iOS 8 中的新功能是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 或更低版本的最低部署目标,请使用 compare with NSStringCompareOptions.NumericSearch UIDevice 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

                          【讨论】:

                            【解决方案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
                            

                            【讨论】:

                            • float versionToBeCompared = 3.1.3; 甚至无法编译。
                            【解决方案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 年之前几乎没用

                            【讨论】:

                              【解决方案24】:
                              1. 在主屏幕中,点按 设置 > 常规 > 关于
                              2. 您设备的软件版本应显示在此屏幕上。
                              3. 检查版本号是否大于3.1.3

                              【讨论】:

                              • 否决我的答案的人能否也请提供他们这样做的动机?那会很有帮助。
                              • 你被否决了,因为你的答案不适合这个网站。问题是如何使用代码检查设备版本,而不是逐步检查设备上的设置。您的答案会更适合“Ask Different”。
                              • @ecnepsnai 但我的意思是,如果这是一个编程问题,至少说一下您使用的编程语言是否有意义?
                              【解决方案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)
                              

                              【讨论】:

                              • 太棒了。最好将它放在 XCode 项目的 .pch 文件中
                              • 我将所有常量放在我的Constants.h 文件中,该文件导入到我的pch 文件中。
                              【解决方案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 可能会发布类的向后兼容版本,如果他们这样做了,那么您建议的代码将永远不会使用它,因为您的逻辑会查找操作系统版本号而不是类的存在。

                              (Source of this information)

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

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

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

                              【讨论】:

                              • 为什么要投反对票?这个解决方案可以完美地使用 Swift 和任何 iOS 版本。尤其是对类存在的检查非常完美。
                              【解决方案27】:
                              #define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
                              

                              【讨论】:

                                【解决方案28】:

                                这是一个快速版本:

                                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
                                }
                                

                                【讨论】:

                                • 我认为第 3-6 行中的版本应该是 iOSVersion,例如 struct iOSVersion { static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue static let iOS7 = (iOSVersion.SYS_VERSION_FLOAT &lt; 8.0 &amp;&amp; iOSVersion.SYS_VERSION_FLOAT &gt;= 7.0) static let iOS8 = (iOSVersion.SYS_VERSION_FLOAT &gt;= 8.0 &amp;&amp; iOSVersion.SYS_VERSION_FLOAT &lt; 9.0) static let iOS9 = (iOSVersion.SYS_VERSION_FLOAT &gt;= 9.0 &amp;&amp; iOSVersion.SYS_VERSION_FLOAT &lt; 10.0) }
                                【解决方案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
                                

                                【讨论】:

                                  【解决方案30】:

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

                                  [[UIDevice currentDevice] systemVersion]
                                  

                                  【讨论】:

                                    猜你喜欢
                                    • 2015-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2020-10-25
                                    • 2011-04-18
                                    相关资源
                                    最近更新 更多