Überprüfen Sie die Betriebssystemversion in Swift?

190

Ich versuche, die Systeminformationen in Swift zu überprüfen. Ich fand heraus, dass dies durch Code erreicht werden kann:

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

Ich habe zwei Probleme mit diesem Code:

  1. Was sollte der Anfangswert von sysData sein? Dieses Beispiel gibt -1 in retVal an, wahrscheinlich weil sysData null ist.
  2. Wie kann ich Informationen aus sysData lesen?
Gergely
quelle

Antworten:

387

Versuchen Sie für iOS:

var systemVersion = UIDevice.current.systemVersion

Versuchen Sie unter OS X:

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

Wenn Sie nur überprüfen möchten, ob auf den Benutzern mindestens eine bestimmte Version ausgeführt wird, können Sie auch die folgende Swift 2-Funktion verwenden, die unter iOS und OS X funktioniert:

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

ABER es wird nicht empfohlen, die Betriebssystemversion zu überprüfen. Es ist besser zu überprüfen, ob die gewünschte Funktion auf dem Gerät verfügbar ist, als die Versionsnummern zu vergleichen. Wie oben erwähnt, sollten Sie unter iOS überprüfen, ob es auf einen Selektor reagiert. z.B.:

if (self.respondsToSelector(Selector("showViewController"))) {
    self.showViewController(vc, sender: self)
} else {
    // some work around
}
miho
quelle
Während dies für Ziel c korrekt ist, gibt es eine viel schönere Möglichkeit, dies schnell zu tun. Hier umrissen
Fogmeister
2
Eine Möglichkeit, die Betriebssystemversion direkt zu überprüfen (im Gegensatz zur Überprüfung auf bestimmte Funktionen), besteht darin, Daten über die Verteilung der Betriebssystemversionen unter Ihren Benutzern zu sammeln, um Ihr niedrigstes Bereitstellungsziel zu ermitteln.
Nicolas Miari
90

Update:
Jetzt sollten Sie die neue Verfügbarkeitsprüfung verwenden, die mit Swift 2 eingeführt wurde:
z. B. Um beim Kompilieren nach iOS 9.0 oder höher zu suchen, verwenden Sie Folgendes:

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

oder kann mit der gesamten Methode oder Klasse verwendet werden

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

Weitere Informationen finden Sie hier .

Laufzeitprüfungen:

Wenn Sie keine genaue Version wünschen, aber iOS 9,10 oder 11 überprüfen möchten, indem Sie Folgendes verwenden:

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

EDIT: Habe gerade einen anderen Weg gefunden, um dies zu erreichen:

let iOS8 = floor(NSFoundationVersionNumber) > floor(NSFoundationVersionNumber_iOS_7_1)
let iOS7 = floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_7_1)
Aks
quelle
50

Ich habe Hilfsfunktionen erstellt, die vom folgenden Link in swift übertragen wurden:

Wie können wir programmgesteuert erkennen, auf welcher iOS-Version das Gerät ausgeführt wird?

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
}

Es kann wie folgt verwendet werden:

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
}
KVISH
quelle
31

Swift 5

Wir müssen keine Erweiterung erstellen, da ProcessInfowir die Versionsinformationen erhalten. Sie können den Beispielcode für iOS wie folgt sehen.

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

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

nahung89
quelle
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
}
neoneye
quelle
1
Warum wird in runNewCode #available (iOS 11.0, *) benötigt?
Illya Krit
1
@IllyaKrit Der #available(...)Block verhindert, dass der Compiler Fehler für Code anzeigt, der in älteren als den bereitgestellten Versionen nicht unterstützt wird.
Future-Adam
15

Ich habe diesen Singleton für die einfache Verwendung erstellt, eine IOSVersion.swiftDatei erstellt und diesen Code hinzugefügt:

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

VERWENDEN :

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

Danke @KVISH

Bearbeiten Sie Swift 2:

if #available(iOS 9.0, *) {
    // 👍 
} else {
    // 👎
}
YannSteph
quelle
4
Ist das Singleton? oder nur Klassenfunktionen auf IOSVersion? wäre kein Singleton static let shared = IOSVersion
Charlton Provatas
9

Wenn Sie Swift 2 verwenden und die Betriebssystemversion überprüfen möchten, um eine bestimmte API zu verwenden, können Sie die neue Verfügbarkeitsfunktion verwenden:

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

Ich habe diese Antwort geschrieben, weil es die erste Frage in Google für die swift 2 check system versionAbfrage ist.

FreeNickname
quelle
7

Update für 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
}
Mellong Lau
quelle
1
Kann überspringen ComparisonResult, um es kürzer zu machen.
John Pang
Das Ausklammern UIDevice.current.systemVersion.compare(version, options: .numeric)in a funckann auch das Lesen von Code erleichtern.
John Pang
5

Einzelheiten

  • Xcode 10.2.1 (10E1001), Swift 5

Links

OperatingSystemVersion

Lösung

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
Wassili Bodnarchuk
quelle
1
Gibt es keine potenziellen Rundungsprobleme bei der Verwendung Doublefür eine Versionsnummer, z. B. 10.0999anstelle von 10.1?
Mschmidt
Nein var stringVersion = "10.0999"; print(stringVersion.toDouble!) // print 10.0999, es wird gedruckt10.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

und überprüfen Sie als

if(iOS8)
{

}
else 
{
}  
poojathorat
quelle
4

Der einfachste und einfachste Weg, die Systemversion (und viele andere Versionen) in Swift 2 und höher zu überprüfen, ist:

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

}

Außerdem #availablekönnen Sie Versionen davon überprüfen:

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift
Tengai
quelle
2

Mattt Thompson teilt einen sehr praktischen Weg

switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
case .OrderedSame, .OrderedDescending:
    println("iOS >= 8.0")
case .OrderedAscending:
    println("iOS < 8.0")
}
dVaffektion
quelle
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
}

Verwendung:

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

PS KVISH Antwort übersetzt in Swift 4.x mit Umbenennen der Funktionen, da ich dieses Snippet speziell für die iOS-App verwende.

Hemang
quelle
1

Hinweis: Verfügbar in iOS 8.0 und höher. OS X 10.10 und höher

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        }
Leo Dabus
quelle
1

Basierend auf der Antwort von Matt Thompson ist hier eine Methode mit entsprechenden Komponententests, die mit Swift und Objective-c unter iOS 7 und höher funktioniert (einschließlich iOS 9 , mit dem Sie die NSFoundationNumber nicht mehr überprüfen können ):

+ (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
quelle
Sie erkennen, dass die eigentliche Methode sehr kurz und kompakt ist und dass ich gerade den Unit-Test-Code hinzugefügt habe, um sie zu veranschaulichen und zu beweisen, dass sie funktioniert, oder?
n8tr
Es tut mir leid, dass ich auf einen Blick nicht bemerkt habe, dass es sich um XCTest handelt.
DawnSong
1
let osVersion = NSProcessInfo.processInfo().operatingSystemVersion
let versionString = osVersion.majorVersion.description + "." + osVersion.minorVersion.description + "." + osVersion.patchVersion.description
print(versionString)
Matjan
quelle
0

Auch wenn Sie WatchOS überprüfen möchten.

Schnell

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

Ziel c

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

Holen Sie sich die aktuelle Version des Systems und teilen Sie es. So können Sie Haupt- und Nebenversion erhalten.

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])")
Mili Shah
quelle
0

Die meisten der hier geschriebenen Beispielcodes führen bei Versionen ohne Null zu unerwarteten Ergebnissen. Beispielsweise,

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

Diese Methode gibt mit der übergebenen Version "10.3.0" in iOS "10.3" nicht true zurück. Diese Art von Ergebnis ist nicht sinnvoll und muss als dieselbe Version angesehen werden. Um ein genaues Vergleichsergebnis zu erhalten, müssen wir alle Zahlenkomponenten in der Versionszeichenfolge vergleichen. Darüber hinaus ist die Bereitstellung globaler Methoden in Großbuchstaben kein guter Weg. Da der in unserem SDK verwendete Versionstyp ein String ist, ist es sinnvoll, die Vergleichsfunktionen in String zu erweitern.

Um die Systemversion zu vergleichen, sollten alle folgenden Beispiele funktionieren.

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

Sie können es in meinem Repository hier https://github.com/DragonCherry/VersionCompare überprüfen

DragonCherry
quelle