我正在用Swift检查系统信息。我发现,这可以通过代码来实现:

var sysData:CMutablePointer<utsname> = nil
let retVal:CInt = uname(sysData)

这段代码有两个问题:

sysData的初始值应该是什么?这个例子在retVal中给出-1可能是因为sysData为nil。 如何从sysData读取信息?


当前回答

更新: 现在你应该使用Swift 2引入的新的可用性检查: 例:要检查iOS 9.0或更高版本的使用,可以这样做:

if #available(iOS 9.0, *) {
  // use UIStackView
} else {
  // show sad face emoji
}

或者可以与整个方法或类一起使用

@available(iOS 9.0, *)
func useStackView() {
    // use UIStackView
}    

或者带着守卫

guard #available(iOS 14, *) else {
    return
}

更多信息请看这个。

更新: 根据Allison的评论,我已经更新了答案,检查仍然是运行时,但编译器可以提前知道&可以显示更好的错误或建议,而你正在处理它。

其他检查方法:

如果你不知道确切的版本,但想检查iOS 9,10或11使用if:

let floatVersion = (UIDevice.current.systemVersion as NSString).floatValue

编辑: 只是找到了另一种实现这一目标的方法:

let iOS8 = floor(NSFoundationVersionNumber) > floor(NSFoundationVersionNumber_iOS_7_1)
let iOS7 = floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_7_1)

其他回答

马特·汤普森分享了一种非常简便的方法

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

Swift 3.0+更新

func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedSame
}

func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedAscending
}

func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) == ComparisonResult.orderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.current.systemVersion.compare(version, options: .numeric) != ComparisonResult.orderedDescending
}

根据Matt Thompson的回答,这里有一个带有各自单元测试的方法,可以在iOS 7及以上版本(包括iOS 9,不再让你检查NSFoundationNumber)上与Swift和Objective-c一起工作:

+ (BOOL) isAtLeastOSVersion:(NSString *)osVersion
{
    switch ([[UIDevice currentDevice].systemVersion compare:osVersion options:NSNumericSearch]) {
        case NSOrderedSame:
        case NSOrderedDescending:
            return YES;
        default:
            return NO;
    }
}  

.

@interface ANFakeCurrDevice : NSObject
@property (nonatomic, strong) NSString *systemVersion;
@end
@implementation ANFakeCurrDevice
@end


@implementation MyHelperClassUnitTests

- (void)setUp {
    [super setUp];
}

- (void)tearDown {
    [super tearDown];
}

- (void)test_isAtLeastOSVersion
{
    id deviceMock = [OCMockObject niceMockForClass:[UIDevice class]];
    ANFakeCurrDevice *fakeCurrDevice = [ANFakeCurrDevice new];
    fakeCurrDevice.systemVersion = @"99.9.9";
    [[[deviceMock stub] andReturn:fakeCurrDevice] currentDevice];
    XCTAssertTrue([[UIDevice currentDevice].systemVersion isEqualToString:@"99.9.9"]);

    fakeCurrDevice.systemVersion = @"1.0.1";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1.0"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"1.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"1.0.2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"1.1.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"2.1.0"]);


    fakeCurrDevice.systemVersion = @"8.4.0";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"7.0.1"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"8.4.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"8.4.2"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0.1"]);
    XCTAssertFalse([ANConstants isAtLeastOSVersion:@"9.0.2"]);
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"] && ![ANConstants isAtLeastOSVersion:@"9.0"]);

    fakeCurrDevice.systemVersion = @"8.4.1";
    XCTAssertTrue([ANConstants isAtLeastOSVersion:@"8.4"] && ![ANConstants isAtLeastOSVersion:@"9.0"]);
}


@end

更新: 现在你应该使用Swift 2引入的新的可用性检查: 例:要检查iOS 9.0或更高版本的使用,可以这样做:

if #available(iOS 9.0, *) {
  // use UIStackView
} else {
  // show sad face emoji
}

或者可以与整个方法或类一起使用

@available(iOS 9.0, *)
func useStackView() {
    // use UIStackView
}    

或者带着守卫

guard #available(iOS 14, *) else {
    return
}

更多信息请看这个。

更新: 根据Allison的评论,我已经更新了答案,检查仍然是运行时,但编译器可以提前知道&可以显示更好的错误或建议,而你正在处理它。

其他检查方法:

如果你不知道确切的版本,但想检查iOS 9,10或11使用if:

let floatVersion = (UIDevice.current.systemVersion as NSString).floatValue

编辑: 只是找到了另一种实现这一目标的方法:

let iOS8 = floor(NSFoundationVersionNumber) > floor(NSFoundationVersionNumber_iOS_7_1)
let iOS7 = floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_7_1)

如果你正在使用Swift 2,并且你想要检查操作系统版本以使用某个API,你可以使用新的可用性特性:

if #available(iOS 8, *) {
    //iOS 8+ code here.
}
else {
    //Code for iOS 7 and older versions.
    //An important note: if you use #availability, Xcode will also 
    //check that you don't use anything that was introduced in iOS 8+
    //inside this `else` block. So, if you try to use UIAlertController
    //here, for instance, it won't compile. And it's great.
}

我写这个答案是因为它是谷歌中swift 2 check系统版本查询的第一个问题。