Periksa versi OS di Swift?


191

Saya mencoba memeriksa informasi sistem di Swift. Saya tahu, bahwa itu bisa dicapai dengan kode:

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

Saya memiliki dua masalah dengan kode ini:

  1. Apa yang seharusnya menjadi nilai awal sysData? Contoh ini memberikan -1 di retVal mungkin karena sysData nil.
  2. Bagaimana saya bisa membaca informasi dari sysData?

Jawaban:


388

Untuk iOS, coba:

var systemVersion = UIDevice.current.systemVersion

Untuk OS X, coba:

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

Jika Anda hanya ingin memeriksa apakah pengguna menjalankan setidaknya versi tertentu, Anda juga dapat menggunakan fitur Swift 2 berikut yang berfungsi pada iOS dan OS X:

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

TETAPI tidak disarankan untuk memeriksa versi OS. Lebih baik untuk memeriksa apakah fitur yang ingin Anda gunakan tersedia di perangkat daripada membandingkan nomor versi. Untuk iOS, seperti yang disebutkan di atas, Anda harus memeriksa apakah itu menanggapi pemilih; misalnya.:

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

Meskipun ini benar untuk tujuan c, ada cara yang jauh lebih baik untuk melakukannya dengan cepat. Diuraikan di sini ... hackingwithswift.com/new-syntax-swift-2-avilities-checking
Fogmeister

2
Satu kegunaan yang saya lihat untuk memeriksa versi OS secara langsung (sebagai lawan memeriksa kemampuan khusus) adalah untuk mengumpulkan data tentang distribusi versi OS di antara pengguna Anda, untuk menentukan target penyebaran terendah Anda.
Nicolas Miari

91

Pembaruan:
Sekarang Anda harus menggunakan pemeriksaan ketersediaan baru yang diperkenalkan dengan Swift 2:
mis. Untuk memeriksa iOS 9.0 atau lebih baru pada waktu kompilasi gunakan ini:

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

atau dapat digunakan dengan seluruh metode atau kelas

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

Untuk info lebih lanjut lihat ini .

Jalankan pemeriksaan waktu:

jika Anda tidak ingin versi yang pasti tetapi ingin memeriksa iOS 9,10 atau 11 menggunakan jika:

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

EDIT: Baru saja menemukan cara lain untuk mencapai ini:

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

50

Saya membuat fungsi pembantu yang ditransfer dari tautan di bawah ke swift:

Bagaimana kita bisa secara terprogram mendeteksi versi iOS yang menjalankan perangkat?

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
}

Dapat digunakan seperti:

SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO("7.0")

Cepat 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

Cepat 5

Kami tidak perlu membuat ekstensi karena ProcessInfomemberi kami info versi. Anda dapat melihat kode sampel untuk iOS seperti di bawah ini.

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")
}

Referensi: http://nshipster.com/swift-system-version-checking/


17

Cepat 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
mengapa di runNewCode diperlukan #available (iOS 11.0, *)?
Illya Krit

1
@IllyaKrit #available(...)Blok menghentikan kompilator menampilkan kesalahan untuk kode di dalam yang tidak didukung di versi yang lebih lama dari yang disediakan.
future-adam

15

Saya membuat Singleton ini untuk penggunaan sederhana, membuat IOSVersion.swiftfile dan menambahkan kode ini:

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

GUNAKAN:

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

Terima kasih @KVISH

Edit Swift 2:

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

4
Apakah itu singleton? atau hanya fungsi kelas di iOSVersion? tidak akan menjadi singleton static let shared = IOSVersion
Charlton Provatas

9

Jika Anda menggunakan Swift 2 dan Anda ingin memeriksa versi OS untuk menggunakan API tertentu, Anda dapat menggunakan fitur ketersediaan baru:

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

Saya menulis jawaban ini karena ini adalah pertanyaan pertama di Google untuk swift 2 check system versionkueri.


7

Pembaruan untuk 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
Dapat melewati ComparisonResultuntuk membuatnya lebih pendek.
John Pang

Juga, UIDevice.current.systemVersion.compare(version, options: .numeric)memasukkan keluar ke dalam funcdapat membantu membaca kode.
John Pang

5

Detail

  • Xcode 10.2.1 (10E1001), Swift 5

Tautan

OperatingSystemVersion

Larutan

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
Apakah tidak ada potensi masalah pembulatan saat menggunakan Doubleuntuk nomor versi, misalnya 10.0999bukan 10.1?
mschmidt

Tidak var stringVersion = "10.0999"; print(stringVersion.toDouble!) // print 10.0999, itu akan dicetak10.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

dan periksa sebagai

if(iOS8)
{

}
else 
{
}  

4

Cara termudah dan paling sederhana untuk memeriksa versi sistem (dan banyak versi lainnya) di Swift 2 dan lebih tinggi adalah:

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

}

Juga, dengan #availableAnda dapat memeriksa versi ini:

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift

2

Mattt Thompson berbagi cara yang sangat praktis

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
}

Pemakaian:

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

Jawaban PS KVISH diterjemahkan ke Swift 4.x dengan mengganti nama fungsi karena saya secara khusus menggunakan cuplikan ini untuk aplikasi iOS.


1

Catatan: Tersedia di iOS 8.0 dan yang lebih baru. OS X v10.10 dan yang lebih baru

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

Berdasarkan jawaban Matt Thompson, berikut adalah metode dengan unit test masing-masing yang bekerja dengan Swift dan Objective-c di iOS 7 dan di atasnya (termasuk iOS 9 yang tidak lagi memungkinkan Anda memeriksa 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

Anda menyadari bahwa metode yang sebenarnya sangat singkat dan ringkas dan saya baru saja menambahkan kode uji unit untuk ilustrasi dan bukti bahwa itu berhasil, kan?
n8tr

Maaf saya gagal menyadari bahwa ini adalah XCTest dalam sekejap.
DawnSong

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

0

Juga jika Anda ingin memeriksa WatchOS.

Cepat

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

Objektif-C

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

0

Dapatkan versi sistem saat ini dan bagilah. Jadi Anda bisa mendapatkan versi mayor dan minor.

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

Sebagian besar kode sampel yang ditulis di sini akan mendapatkan hasil yang tidak terduga dengan versi ekstra nol. Sebagai contoh,

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

Metode ini tidak akan kembali benar dengan versi yang lulus "10.3.0" di iOS "10.3". Hasil semacam ini tidak masuk akal dan mereka harus dianggap sebagai versi yang sama. Untuk mendapatkan hasil perbandingan yang akurat, kita harus mempertimbangkan membandingkan semua komponen angka dalam string versi. Plus, memberikan metode global dalam semua huruf kapital bukan cara yang baik untuk pergi. Karena tipe versi yang kami gunakan di SDK kami adalah sebuah String, masuk akal untuk memperluas fungsi membandingkan dalam String.

Untuk membandingkan versi sistem, semua contoh berikut harus berfungsi.

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"))

Anda dapat memeriksanya di repositori saya di sini https://github.com/DragonCherry/VersionCompare

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.