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

[[UIDevice currentDevice].systemVersion floatValue]

但是不管用,我只想要一个:

if (version > 3.1.3) { }

我怎样才能做到这一点呢?


当前回答

快速的例子,实际工作:

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年之前几乎没用

其他回答

基本上和这个想法一样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);
/*
 *  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")) {
    ...
}

简单的回答是……

从Swift 2.0开始,你可以在if或guard中使用#available来保护那些只能在特定系统上运行的代码。

if #available(iOS 9, *) {} 在Objective-C中,您需要检查系统版本并进行比较。

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

从Xcode 9开始:

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

完整的答案是……

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

检查api的存在:

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

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

对于弱链接的类,直接向类发送消息是安全的。值得注意的是,这适用于没有显式链接为“Required”的框架。对于缺少的类,表达式的计算结果为nil,不满足条件:

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

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

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。苹果在他们的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)。

首选的方法

在Swift 2.0中,苹果使用更方便的语法添加了可用性检查(点击这里阅读更多)。现在你可以用更简洁的语法检查操作系统版本:

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

这是首选检查respondsToSelector等(什么是新的在Swift)。现在,如果你没有正确地保护你的代码,编译器总是会警告你。


斯威夫特2.0

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

在iOS 8及更高版本上部署

对于iOS 8.0或以上版本的最低部署目标,使用NSProcessInfo operatingSystemVersion或isOperatingSystemAtLeastVersion。

这将产生以下结果:

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。UIDevice systemVersion上的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。

一个在obj - c++ 11中更通用的版本(你可能会用NSString/C函数替换其中的一些东西,但这不是那么冗长。这给了你两种机制。splitSystemVersion为你提供了一个包含所有部分的数组,如果你只是想打开主版本(例如switch([self splitSystemVersion][0]) {case 4: break;案例5:断裂;})。

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