Kiểm tra phiên bản HĐH trong Swift?


190

Tôi đang cố kiểm tra thông tin hệ thống trong Swift. Tôi đã tìm ra rằng nó có thể đạt được bằng mã:

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

Tôi có hai vấn đề với mã này:

  1. Giá trị ban đầu của sysData là gì? Ví dụ này cho -1 trong retVal có thể vì sysData là nil.
  2. Làm thế nào tôi có thể đọc thông tin từ sysData?

Câu trả lời:


387

Đối với iOS, hãy thử:

var systemVersion = UIDevice.current.systemVersion

Đối với OS X, hãy thử:

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

Nếu bạn chỉ muốn kiểm tra xem người dùng có đang chạy ít nhất một phiên bản cụ thể hay không, bạn cũng có thể sử dụng tính năng Swift 2 sau hoạt động trên iOS và OS X:

if #available(iOS 9.0, *) {
    // use the feature only available in iOS 9
    // for ex. UIStackView
} else {
    // or use some work around
}

NHƯNG không nên kiểm tra phiên bản HĐH. Tốt hơn là kiểm tra xem tính năng bạn muốn sử dụng có khả dụng trên thiết bị hay không so với số phiên bản. Đối với iOS, như đã đề cập ở trên, bạn nên kiểm tra xem nó có phản hồi với bộ chọn hay không; ví dụ.:

if (self.respondsToSelector(Selector("showViewController"))) {
    self.showViewController(vc, sender: self)
} else {
    // some work around
}

Trong khi điều này là chính xác cho mục tiêu c, có một cách tốt hơn để làm điều đó nhanh chóng. Được phác thảo ở đây ... hackingwithswift.com/new-syntax-swift-2-avcellence-checking
Fogmeister

2
Một cách sử dụng tôi có thể thấy để kiểm tra trực tiếp phiên bản HĐH (trái ngược với việc kiểm tra các khả năng cụ thể) là thu thập dữ liệu về phân phối phiên bản HĐH giữa những người dùng của bạn, để xác định mục tiêu triển khai thấp nhất của bạn.
Nicolas Miari

90

Cập nhật:
Bây giờ bạn nên sử dụng kiểm tra tính khả dụng mới được giới thiệu với Swift 2:
ví dụ: Để kiểm tra iOS 9.0 trở lên tại thời điểm biên dịch, hãy sử dụng cách này:

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

hoặc có thể được sử dụng với toàn bộ phương thức hoặc lớp

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

Để biết thêm thông tin xem này .

Chạy kiểm tra thời gian:

nếu bạn không muốn phiên bản chính xác nhưng muốn kiểm tra iOS 9,10 hoặc 11 bằng cách sử dụng if:

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

EDIT: Chỉ cần tìm một cách khác để đạt được điều này:

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

50

Tôi đã thực hiện các chức năng trợ giúp được chuyển từ liên kết bên dưới thành swift:

Làm cách nào chúng tôi có thể lập trình phát hiện phiên bản iOS nào là thiết bị đang chạy?

func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
}

func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
}

func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
}

func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
    return UIDevice.currentDevice().systemVersion.compare(version,
        options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
}

Nó có thể được sử dụng như vậy:

SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO("7.0")

Swift 4.2

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

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

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

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

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

31

Swift 5

Chúng tôi không cần tạo tiện ích mở rộng kể từ khi ProcessInfo cung cấp cho chúng tôi thông tin phiên bản. Bạn có thể xem mã mẫu cho iOS như dưới đây.

let os = ProcessInfo().operatingSystemVersion

switch (os.majorVersion, os.minorVersion, os.patchVersion) {
case (let x, _, _) where x < 8:
    print("iOS < 8.0.0"

case (8, 0, _):
    print("iOS >= 8.0.0, < 8.1.0")

case (8, _, _):
    print("iOS >= 8.1.0, < 9.0")

case (9, _, _):
    print("iOS >= 9.0.0")

default:
    print("iOS >= 10.0.0")
}

Tham khảo: http://nshipster.com/swift-system-version-checking/


17

Swift 5

func run() {
    let version = OperatingSystemVersion(majorVersion: 13, minorVersion: 0, patchVersion: 0)
    if ProcessInfo.processInfo.isOperatingSystemAtLeast(version) {
        runNewCode()
    } else {
        runLegacyCode()
    }
}

func runNewCode() {
    guard #available(iOS 13.0, *) else {
        fatalError()
    }
    // do new stuff
}

func runLegacyCode() {
    // do old stuff
}

1
tại sao trong runNewCode lại cần #av Available (iOS 11.0, *)?
Illya Krit

1
@IllyaKrit #available(...)Khối ngăn trình biên dịch hiển thị lỗi cho mã trong đó không được hỗ trợ trong các phiên bản cũ hơn được cung cấp.
adam tương lai

15

Tôi đã tạo Singleton này để sử dụng đơn giản, tạo một IOSVersion.swifttệp và thêm mã này:

import UIKit

public class IOSVersion {
    class func SYSTEM_VERSION_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
    }

    class func SYSTEM_VERSION_GREATER_THAN(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
    }

    class func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
    }

    class func SYSTEM_VERSION_LESS_THAN(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
    }

    class func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: NSString) -> Bool {
        return UIDevice.currentDevice().systemVersion.compare(version as String,
            options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
    }
}

SỬ DỤNG :

IOSVersion.SYSTEM_VERSION_EQUAL_TO("8.0")
IOSVersion.SYSTEM_VERSION_LESS_THAN("8.0")

Cảm ơn @KVISH

Chỉnh sửa Swift 2:

if #available(iOS 9.0, *) {
    // 👍 
} else {
    // 👎
}

4
Có phải đó là đơn? hoặc chỉ các chức năng lớp học trên IOSVersion? sẽ không phải là người độc thân static let shared = IOSVersion
Charlton Provatas

9

Nếu bạn đang sử dụng Swift 2 và bạn muốn kiểm tra phiên bản HĐH để sử dụng một API nhất định, bạn có thể sử dụng tính năng khả dụng mới:

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

Tôi đã viết câu trả lời này vì đây là câu hỏi đầu tiên trong Google cho swift 2 check system versiontruy vấn.


7

Cập nhật cho 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
}

1
Có thể bỏ qua ComparisonResultđể làm cho nó ngắn hơn.
John Pang

Ngoài ra, bao thanh toán UIDevice.current.systemVersion.compare(version, options: .numeric)ra funccó thể giúp đọc mã.
John Pang

5

Chi tiết

  • Xcode 10.2.1 (10E1001), Swift 5

Liên kết

OperationsSystemVersion

Giải pháp

extension OperatingSystemVersion {
    func getFullVersion(separator: String = ".") -> String {
        return "\(majorVersion)\(separator)\(minorVersion)\(separator)\(patchVersion)"
    }
}

let os = ProcessInfo().operatingSystemVersion
print(os.majorVersion)          // 12
print(os.minorVersion)          // 2
print(os.patchVersion)          // 0
print(os.getFullVersion())      // 12.2.0

1
Không có vấn đề làm tròn tiềm năng khi sử dụng Doublecho một số phiên bản, ví dụ 10.0999thay vì 10.1?
mschmidt

Không var stringVersion = "10.0999"; print(stringVersion.toDouble!) // print 10.0999, nó sẽ in10.0999
Vasily Bodnarchuk

4
let Device = UIDevice.currentDevice()
let iosVersion = NSString(string: Device.systemVersion).doubleValue

let iOS8 = iosVersion >= 8
let iOS7 = iosVersion >= 7 && iosVersion < 8

và kiểm tra như

if(iOS8)
{

}
else 
{
}  

4

Cách dễ nhất và đơn giản nhất để kiểm tra phiên bản hệ thống (và rất nhiều phiên bản khác) trong Swift 2 trở lên là:

if #available(iOS 9.0, *) { // check for iOS 9.0 and later

}

Ngoài ra, với #availablebạn có thể kiểm tra các phiên bản sau:

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift

2

Mattt Thompson chia sẻ một cách rất tiện dụng

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

2

Swift 4.x

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

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

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

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

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

Sử dụng:

if iOS_VERSION_GREATER_THAN_OR_EQUAL_TO(version: "11.0") {
    //Do something!
}

Câu trả lời PS KVISH được dịch sang Swift 4.x với việc đổi tên các chức năng vì tôi đặc biệt sử dụng đoạn mã này cho ứng dụng iOS.


1

Lưu ý: Có sẵn trong iOS 8.0 trở lên. OS X v10.10 trở lên

var majorVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.majorVersion }
var minorVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.minorVersion }
var patchVersion: Int    { return NSProcessInfo.processInfo().operatingSystemVersion.patchVersion }
var myOSVersion:  String { return NSProcessInfo.processInfo().operatingSystemVersionString        }

1

Dựa trên câu trả lời của Matt Thompson, đây là một phương pháp với các bài kiểm tra đơn vị tương ứng hoạt động với SwiftObjective-c trên iOS 7 trở lên (bao gồm cả iOS 9 không còn cho phép bạn kiểm tra NSFoundationNumber ):

+ (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

bạn có nhận ra rằng phương pháp thực tế rất ngắn và gọn và tôi chỉ cần thêm mã kiểm tra đơn vị để minh họa và bằng chứng rằng nó hoạt động, phải không?
n8tr

Tôi xin lỗi vì tôi đã không nhận ra rằng đó là XCTest trong nháy mắt.
DawnSong

1
let osVersion = NSProcessInfo.processInfo().operatingSystemVersion
let versionString = osVersion.majorVersion.description + "." + osVersion.minorVersion.description + "." + osVersion.patchVersion.description
print(versionString)

0

Ngoài ra nếu bạn muốn kiểm tra WatchOS.

Nhanh

let watchOSVersion = WKInterfaceDevice.currentDevice().systemVersion
print("WatchOS version: \(watchOSVersion)")

Mục tiêu-C

NSString *watchOSVersion = [[WKInterfaceDevice currentDevice] systemVersion];
NSLog(@"WatchOS version: %@", watchOSVersion);

0

Nhận phiên bản hiện tại của hệ thống và phân chia nó. Vì vậy, bạn có thể nhận được phiên bản lớn và nhỏ.

let sys_version = UIDevice.current.systemVersion
let all_version = sys_version.components(separatedBy: ".")
print("Major version : \(all_version[0])")
print("Minor version : \(all_version[1])")

0

Hầu hết các mã mẫu được viết ở đây sẽ nhận được kết quả bất ngờ với các phiên bản khác không. Ví dụ,

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

Phương pháp này sẽ không trở lại đúng với phiên bản đã qua "10.3.0" trong iOS "10.3". Loại kết quả này không có ý nghĩa và chúng phải được coi là cùng một phiên bản. Để có kết quả so sánh chính xác, chúng tôi phải xem xét so sánh tất cả các thành phần số trong chuỗi phiên bản. Thêm vào đó, cung cấp các phương thức toàn cầu trong tất cả các chữ in hoa không phải là một cách tốt để đi. Vì loại phiên bản chúng tôi sử dụng trong SDK của mình là Chuỗi, nên có ý nghĩa mở rộng chức năng so sánh trong Chuỗi.

Để so sánh phiên bản hệ thống, tất cả các ví dụ sau sẽ hoạt động.

XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThan: "99.0.0"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(equalTo: UIDevice.current.systemVersion))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThan: "3.5.99"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(lessThanOrEqualTo: "10.3.0.0.0.0.0.0"))
XCTAssertTrue(UIDevice.current.systemVersion.isVersion(greaterThanOrEqualTo: "10.3"))

Bạn có thể kiểm tra nó trong kho lưu trữ của tôi ở đây https://github.com/DragonCherry/VersionCompare

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.