ตรวจสอบเวอร์ชั่นของระบบปฏิบัติการใน Swift?


191

ฉันพยายามตรวจสอบข้อมูลระบบใน Swift ฉันคิดออกว่ามันสามารถทำได้โดยรหัส:

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

ฉันมีปัญหาสองประการเกี่ยวกับรหัสนี้:

  1. สิ่งที่ควรเป็นค่าเริ่มต้นของ sysData ตัวอย่างนี้ให้ -1 ใน retVal อาจเป็นเพราะ sysData เป็นศูนย์
  2. ฉันจะอ่านข้อมูลจาก sysData ได้อย่างไร

คำตอบ:


388

สำหรับ iOS ลอง:

var systemVersion = UIDevice.current.systemVersion

สำหรับ OS X ให้ลอง:

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

หากคุณต้องการตรวจสอบว่าผู้ใช้ทำงานอย่างน้อยรุ่นที่ระบุหรือไม่คุณยังสามารถใช้คุณสมบัติ Swift 2 ซึ่งทำงานบน iOS และ OS X ได้:

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

แต่ไม่แนะนำให้ตรวจสอบเวอร์ชั่นของระบบปฏิบัติการ เป็นการดีกว่าที่จะตรวจสอบว่าคุณลักษณะที่คุณต้องการใช้นั้นมีอยู่ในอุปกรณ์หรือไม่มากกว่าการเปรียบเทียบหมายเลขรุ่น สำหรับ iOS ตามที่กล่าวไว้ข้างต้นคุณควรตรวจสอบว่ามันตอบสนองต่อตัวเลือกหรือไม่ เช่น.:

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

ในขณะที่สิ่งนี้ถูกต้องสำหรับวัตถุประสงค์ c มีวิธีที่ดีกว่าในการทำอย่างรวดเร็ว สรุปไว้ที่นี่ ... hackingwithswift.com/new-syntax-swift-2-availability-checking
Fogmeister

2
ใช้ครั้งเดียวฉันสามารถดูการตรวจสอบเวอร์ชั่นของระบบปฏิบัติการโดยตรง (ซึ่งต่างจากการตรวจสอบความสามารถเฉพาะ) คือการรวบรวมข้อมูลเกี่ยวกับการแจกจ่ายเวอร์ชันของระบบปฏิบัติการในหมู่ผู้ใช้ของคุณ
Nicolas Miari

91

อัปเดต:
ตอนนี้คุณควรใช้การตรวจสอบความพร้อมใช้งานใหม่ที่เปิดตัวกับ 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
}

สำหรับข้อมูลเพิ่มเติมโปรดดูที่นี้

ตรวจสอบเวลาทำงาน:

หากคุณไม่ต้องการรุ่นที่แน่นอน แต่ต้องการตรวจสอบ iOS 9,10 หรือ 11 โดยใช้ถ้า:

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)

50

ฉันสร้างฟังก์ชั่นผู้ช่วยที่ถ่ายโอนจากลิงก์ด้านล่างไปยังสวิฟท์:

เราจะตรวจสอบโปรแกรมเวอร์ชัน iOS ที่อุปกรณ์ใช้งานโดยทางโปรแกรมอย่างไร

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
}

มันสามารถใช้เช่น:

SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO("7.0")

สวิฟท์ 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

สวิฟท์ 5

เราไม่จำเป็นต้องสร้างส่วนขยายเนื่องจากProcessInfoให้ข้อมูลรุ่นแก่เรา คุณสามารถดูโค้ดตัวอย่างสำหรับ iOS ได้ด้านล่าง

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

การอ้างอิง: http://nshipster.com/swift-system-version-checking/


17

สวิฟท์ 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
ทำไมใน runNewCode ถึงจำเป็น #available (iOS 11.0, *) จำเป็น?
Illya Krit

1
@IllyaKrit #available(...)บล็อกหยุดคอมไพเลอร์จากการแสดงข้อผิดพลาดสำหรับรหัสภายในที่ไม่ได้รับการสนับสนุนในรุ่นเก่ากว่าที่ระบุไว้
future-adam

15

ฉันทำ Singleton นี้เพื่อใช้ง่ายสร้างIOSVersion.swiftไฟล์และเพิ่มรหัสนี้:

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

ใช้:

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

ขอบคุณ @KVISH

แก้ไข Swift 2:

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

4
ซิงเกิลนั่นไหม หรือแค่ฟังก์ชั่นคลาสบน IOSVersion? จะไม่เป็นคน static let shared = IOSVersion
Charlton Provatas

9

หากคุณใช้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.
}

ฉันเขียนคำตอบนี้เพราะเป็นคำถามแรกใน Google สำหรับการswift 2 check system versionสืบค้น


7

อัปเดตสำหรับ 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
สามารถข้ามComparisonResultเพื่อทำให้สั้นกว่า
John Pang

นอกจากนี้การแยกUIDevice.current.systemVersion.compare(version, options: .numeric)ออกเป็นfuncสามารถช่วยอ่านรหัส
John Pang

5

รายละเอียด

  • Xcode 10.2.1 (10E1001), Swift 5

การเชื่อมโยง

OperatingSystemVersion

สารละลาย

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
ไม่มีปัญหาการปัดเศษที่อาจเกิดขึ้นเมื่อใช้Doubleสำหรับหมายเลขรุ่นเช่น10.0999แทนที่จะเป็น10.1?
mschmidt

ไม่var stringVersion = "10.0999"; print(stringVersion.toDouble!) // print 10.0999มันจะพิมพ์10.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

และตรวจสอบเป็น

if(iOS8)
{

}
else 
{
}  

4

วิธีที่ง่ายที่สุดและง่ายที่สุดในการตรวจสอบเวอร์ชั่นของระบบ (และเวอร์ชั่นอื่น ๆ อีกมากมาย) ใน Swift 2 และสูงกว่าคือ:

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

}

นอกจากนี้#availableคุณสามารถตรวจสอบเวอร์ชันเหล่านี้ได้ด้วย:

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift

2

Mattt Thompson แบ่งปันวิธีที่มีประโยชน์มาก

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
}

การใช้งาน:

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

คำตอบ PS KVISH แปลเป็น Swift 4.x ด้วยการเปลี่ยนชื่อฟังก์ชั่นในขณะที่ฉันกำลังใช้ตัวอย่างข้อมูลนี้สำหรับแอพ iOS


1

หมายเหตุ: มีให้ใน iOS 8.0 และใหม่กว่า OS X v10.10 และใหม่กว่า

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

ตามคำตอบของ Matt Thompson ต่อไปนี้เป็นวิธีการทดสอบหน่วยที่เกี่ยวข้องกับSwiftและObjective-cบนiOS 7 ขึ้นไป (รวมถึงiOS 9ที่ไม่ให้คุณตรวจสอบหมายเลข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

คุณรู้หรือไม่ว่าวิธีการที่เกิดขึ้นจริงนั้นสั้นและกะทัดรัดและฉันเพิ่งเพิ่มรหัสทดสอบหน่วยเพื่อประกอบการสาธิตและการพิสูจน์ว่าใช้ได้จริงไหม?
n8tr

ฉันขอโทษที่ฉันล้มเหลวที่จะรู้ว่ามันเป็น XCTest ได้อย่างรวดเร็ว
DawnSong

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

0

นอกจากนี้หากคุณต้องการตรวจสอบ WatchOS

รวดเร็ว

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

Objective-C

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

0

รับรุ่นปัจจุบันของระบบและแยกมัน ดังนั้นคุณสามารถรับรุ่นหลักและรุ่นรองได้

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

โค้ดตัวอย่างส่วนใหญ่ที่เขียนที่นี่จะได้ผลลัพธ์ที่ไม่คาดคิดโดยมีรุ่นที่เป็นศูนย์พิเศษ ตัวอย่างเช่น,

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

วิธีนี้จะไม่คืนจริงเมื่อใช้เวอร์ชัน "10.3.0" ใน iOS "10.3" ผลลัพธ์ประเภทนี้ไม่สมเหตุสมผลและจะต้องถือเป็นเวอร์ชันเดียวกัน เพื่อให้ได้ผลลัพธ์การเปรียบเทียบที่ถูกต้องเราต้องพิจารณาเปรียบเทียบส่วนประกอบจำนวนทั้งหมดในสตริงเวอร์ชัน นอกจากนี้การให้วิธีการทั่วโลกในตัวพิมพ์ใหญ่ทั้งหมดไม่ใช่วิธีที่ดีที่จะไป เนื่องจากประเภทของรุ่นที่เราใช้ใน SDK ของเรานั้นเป็นสตริงจึงเหมาะสมที่จะขยายการเปรียบเทียบการทำงานใน String

ในการเปรียบเทียบรุ่นของระบบตัวอย่างทั้งหมดต่อไปนี้ควรใช้งานได้

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

คุณสามารถตรวจสอบได้ในพื้นที่เก็บข้อมูลของฉันที่นี่ https://github.com/DragonCherry/VersionCompare

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.