如何检查iOS版本?

908

我想检查设备的iOS版本是否大于3.1.3。我尝试了以下方法:

[[UIDevice currentDevice].systemVersion floatValue]

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

if (version > 3.1.3) { }

我该如何实现这个?


7
主持人提示: 随着时间的推移,这个问题已经有了30多个答案。在添加新答案之前,请务必确认您的解决方案尚未提供。 - Matt
5
从 Xcode 7 开始,在 Swift 中使用 if #available(iOS 9, *) {}。从 Xcode 9 开始,在 Objective-C 中使用 if (@available(iOS 11, *)) {} - Cœur
36个回答

0

基本上与这个想法https://dev59.com/yXA75IYBdhLWcg3wW3oZ#19903595相同,但更加健壮:

#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);

-1
在您的项目中添加以下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)
    }
}

-1

我的解决方案是在你的工具类(提示提示)中添加一个实用方法来解析系统版本并手动补偿浮点数排序。

此外,这段代码相当简单,所以我希望它能帮助一些新手。只需传入目标浮点数,就可以得到一个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;
 }

-1

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

  1. 使用 NSNumericSearch 比较字符串有时会产生令人费解的结果(所有的 SYSTEM_VERSION_* 宏都受到此影响):

    [@"10.0" compare:@"10" options:NSNumericSearch] // 返回 NSOrderedDescending 而不是 NSOrderedSame
    

    解决方法:首先将您的字符串规范化,然后再进行比较。尝试让两个字符串格式完全相同可能会很烦人。

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

    NSFoundationVersionNumber_iOS_6_1 // 在 iOS 5 SDK 中不存在
    

    解决方法:执行两个单独的测试以确保符号存在,然后再比较符号。但这里还有一个问题:

  3. 基础框架版本符号不是唯一的 iOS 版本。多个 iOS 发布版本可以具有相同的框架版本。

    9.29.3 都是 1242.12
    8.38.4 都是 1144.17
    

    解决方法:我认为这个问题是无法解决的。


为了解决这些问题,以下方法将版本号字符串视为基于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; 更改 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");
}

-4

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

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


这并没有回答任何问题。 - Andres Canella
@AndresCanella 我猜答案是 if (SYSTEM_VERSION_GREATER_THAN(@"7.0")){(..CODE...)},所以它回答了问题,对吧? - HelloGoodbye
@HelloGoodbye 不,这并没有回答主题问题。它含糊地建议使用定义,但它并没有包括定义的实际代码。例如:#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 回答应直接与主题问题相关,并且应该清晰明了。这就是为什么它被投票否决的原因。 - Andres Canella

-5
  1. 从主屏幕上,点击设置 > 通用 > 关于本机
  2. 您的设备软件版本应该会显示在这个屏幕上。
  3. 检查版本号是否大于3.1.3

能否给对我的回答投下负评的人提供一下他们这样做的动机呢?这将会很有帮助。 - HelloGoodbye
你被踩是因为你的回答不适合这个网站。问题是如何使用代码检查设备版本,而不是逐步检查设备设置。你的回答更适合Ask Different网站。 - ecnepsnai
@ecnepsnai 但我的意思是,如果这是一个编程问题,至少说一下你正在使用的编程语言不是很合理吗? - HelloGoodbye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接