Swift'te işletim sistemi sürümü kontrol edilsin mi?


191

Swift'te sistem bilgilerini kontrol etmeye çalışıyorum. Kod ile elde edilebileceğini anladım:

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

Bu kod ile iki sorunum var:

  1. SysData'nın başlangıç ​​değeri ne olmalıdır? Bu örnek, muhtemelen sysData nil olduğu için retVal'da -1 verir.
  2. SysData'dan bilgileri nasıl okuyabilirim?

Yanıtlar:


388

İOS için şunları deneyin:

var systemVersion = UIDevice.current.systemVersion

OS X için şunu deneyin:

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

Kullanıcıların en azından belirli bir sürümü çalıştırıp çalıştırmadığını kontrol etmek istiyorsanız, iOS ve OS X'te çalışan aşağıdaki Swift 2 özelliğini de kullanabilirsiniz:

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

AMA işletim sistemi sürümünü kontrol etmeniz önerilmez. Kullanmak istediğiniz özelliğin cihazda mevcut olup olmadığını kontrol etmek sürüm numaralarını karşılaştırmaktan daha iyidir. İOS için, yukarıda belirtildiği gibi, bir seçiciye yanıt verip vermediğini kontrol etmelisiniz; Örneğin.:

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

Bu objektif c için doğru olsa da, hızlı bir şekilde yapmanın çok daha güzel bir yolu var. Burada özetlenen
Fogmeister

2
İşletim sistemi sürümünü doğrudan kontrol etmek için görebildiğim bir kullanım (belirli yetenekleri kontrol etmek yerine), kullanıcılarınız arasındaki işletim sistemi sürümü dağıtımı hakkında veri toplamak, en düşük dağıtım hedefinizi belirlemek.
Nicolas Miari

91

Güncelleme:
Şimdi Swift 2 ile sunulan yeni kullanılabilirlik kontrolünü kullanmalısınız :
örn. Derleme zamanında iOS 9.0 veya üstünü kontrol etmek için şunu kullanın:

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

veya tüm yöntem veya sınıfla kullanılabilir

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

Daha fazla bilgi için bkz bu .

Çalışma süresi kontrolleri:

tam sürümü istemiyorsanız ancak şu durumlarda kullanarak iOS 9,10 veya 11'i kontrol etmek istiyorsanız:

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

EDIT: Sadece bunu başarmak için başka bir yol buldum:

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

50

Aşağıdaki linkten hızlıca aktarılan yardımcı fonksiyonlar yaptım:

Cihazın hangi iOS sürümünün çalıştığını programlı olarak nasıl tespit edebiliriz?

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
}

Şu şekilde kullanılabilir:

SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO("7.0")

Hızlı 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

Hızlı 5

ProcessInfoBize sürüm bilgilerini verdiği için uzantı oluşturmamız gerekmez . İOS için örnek kodu aşağıdaki gibi görebilirsiniz.

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

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


17

Hızlı 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'da #available (iOS 11.0, *) neden gereklidir?
Illya Krit

1
@IllyaKrit #available(...)Blok, derleyicinin, sağlandığından daha eski sürümlerde desteklenmeyen kod hataları göstermesini durdurur.
future-adam

15

Bu Singleton'u basit kullanım için yaptım, bir IOSVersion.swiftdosya oluşturdum ve bu kodu ekledim:

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

KULLANIM:

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

Teşekkürler @KVISH

Swift 2'yi Düzenle:

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

4
Bu singleton mu? ya da sadece IOSVersion'daki sınıf işlevleri? singleton olmaz static let shared = IOSVersion
Charlton Provatas

9

Swift 2 kullanıyorsanız ve belirli bir API'yı kullanmak için işletim sistemi sürümünü kontrol etmek istiyorsanız, yeni kullanılabilirlik özelliğini kullanabilirsiniz:

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

Bu yanıtı yazdım, çünkü bu swift 2 check system versionsorgu için Google'daki ilk soru .


7

Swift 3.0+ için güncelleme

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
ComparisonResultDaha kısa yapmak için atlayabilir .
John Pang

Ayrıca, UIDevice.current.systemVersion.compare(version, options: .numeric)bir içine çarpan funckod okuma yardımcı olabilir.
John Pang

5

ayrıntılar

  • Xcode 10.2.1 (10E1001), Swift 5

Bağlantılar

OperatingSystemVersion

Çözüm

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
DoubleBir sürüm numarası için kullanılırken , örneğin 10.0999yerine yuvarlama problemleri yok 10.1mu?
mschmidt

Hayır. var stringVersion = "10.0999"; print(stringVersion.toDouble!) // print 10.0999Yazdırılacak10.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

ve kontrol et

if(iOS8)
{

}
else 
{
}  

4

Swift 2 ve sonraki sürümlerde sistem sürümünü (ve diğer birçok sürümü) kontrol etmenin en kolay ve basit yolu:

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

}

Ayrıca, #availablebunların sürümlerini kontrol edebilirsiniz:

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift

2

Mattt Thompson çok kullanışlı bir yol paylaşıyor

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
}

Kullanımı:

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

PS KVISH yanıtı, özellikle iOS uygulaması için bu snippet'i kullandığım gibi işlevlerin yeniden adlandırılmasıyla Swift 4.x'e çevrildi.


1

Not: iOS 8.0 ve sonraki sürümlerinde kullanılabilir. OS Xv10.10 ve üstü

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'ın cevap dayanarak, burada çalışır ilgili birim testleri ile bir yöntemdir Swift ve Objective-c üzerinde iOS 7 ve üstü (dahil iOS 9 artık kontrol yapalım 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

gerçek yöntemin çok kısa ve kompakt olduğunu ve sadece örnek test kodunu eklediğimi ve işe yaradığını kanıtlamak için eklediğimi anlıyorsunuz, değil mi?
n8tr

Bir bakışta XCTest olduğunu anlayamadığım için üzgünüm.
DawnSong

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

0

Ayrıca WatchOS'u kontrol etmek istiyorsanız.

hızlı

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

Objective-C

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

0

Sistemin güncel sürümünü alın ve bölün. Böylece büyük ve küçük sürümleri alabilirsiniz.

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

Burada yazılan örnek kodların çoğu, sıfırdan farklı sürümlerde beklenmedik sonuçlar alır. Örneğin,

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

Bu yöntem, iOS "10.3" sürümünde "10.3.0" geçirilmiş sürümüyle true değerini döndürmez. Bu tür bir sonuç mantıklı değildir ve aynı sürüm olarak kabul edilmelidir. Doğru karşılaştırma sonucu elde etmek için sürüm dizesindeki tüm sayı bileşenlerini karşılaştırmayı düşünmeliyiz. Ayrıca, tüm büyük harflerle küresel yöntemler sağlamak iyi bir yol değildir. SDK'mızda kullandığımız sürüm türü bir String olduğundan, String'deki karşılaştırma işlevinin genişletilmesi mantıklıdır.

Sistem sürümünü karşılaştırmak için aşağıdaki örneklerin tümü çalışmalıdır.

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

Depomda buradan kontrol edebilirsiniz https://github.com/DragonCherry/VersionCompare

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.