Comprobar la versión del sistema operativo en Swift?


191

Estoy tratando de verificar la información del sistema en Swift. Me di cuenta de que se podía lograr por código:

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

Tengo dos problemas con este código:

  1. ¿Cuál debería ser el valor inicial de sysData? Este ejemplo da -1 en retVal probablemente porque sysData es nulo.
  2. ¿Cómo puedo leer información de sysData?

Respuestas:


388

Para iOS, intente:

var systemVersion = UIDevice.current.systemVersion

Para OS X, intente:

var systemVersion = NSProcessInfo.processInfo().operatingSystemVersion

Si solo desea verificar si los usuarios están ejecutando al menos una versión específica, también puede usar la siguiente función Swift 2 que funciona en iOS y OS X:

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

PERO no se recomienda verificar la versión del sistema operativo. Es mejor verificar si la función que desea usar está disponible en el dispositivo que comparar los números de versión. Para iOS, como se mencionó anteriormente, debe verificar si responde a un selector; p.ej.:

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

Si bien esto es correcto para el objetivo c, hay una manera mucho mejor de hacerlo rápidamente. Esbozado
Fogmeister

2
Un uso que puedo ver para verificar la versión del sistema operativo directamente (en lugar de verificar las capacidades específicas) es recopilar datos sobre la distribución de la versión del sistema operativo entre sus usuarios, para determinar su objetivo de implementación más bajo.
Nicolas Miari

91

Actualización:
ahora debe usar la nueva verificación de disponibilidad introducida con Swift 2:
por ejemplo, para verificar iOS 9.0 o posterior en tiempo de compilación, use esto:

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

o se puede usar con todo el método o clase

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

Para más información mira esto .

Verificaciones de tiempo de ejecución:

si no quieres la versión exacta pero quieres verificar iOS 9,10 u 11 usando if:

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

EDITAR: Acabo de encontrar otra forma de lograr esto:

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

50

Realicé funciones de ayuda que se transfirieron desde el siguiente enlace a swift:

¿Cómo podemos detectar mediante programación en qué versión de iOS se está ejecutando el dispositivo?

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
}

Se puede usar así:

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

No necesitamos crear una extensión ya ProcessInfoque nos da la información de la versión. Puede ver el código de muestra para iOS como se muestra a continuación.

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

Referencia: 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
¿Por qué en runNewCode se necesita #available (iOS 11.0, *)?
Illya Krit

1
@IllyaKrit El #available(...)bloque impide que el compilador muestre errores para el código que no se admite en versiones anteriores a las proporcionadas.
future-adam

15

Hice este Singleton para un uso simple, creé un IOSVersion.swiftarchivo y agregué este código:

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

UTILIZAR :

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

Gracias @KVISH

Editar Swift 2:

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

44
¿Es ese singleton? o simplemente funciones de clase en IOSVersion? no sería un singleton static let shared = IOSVersion
Charlton Provatas

9

Si está utilizando Swift 2 y desea verificar la versión del sistema operativo para usar una determinada API, puede usar la nueva función de disponibilidad:

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

Escribí esta respuesta porque es la primera pregunta en Google para la swift 2 check system versionconsulta.


7

Actualización para 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
Puede saltar ComparisonResultpara hacerlo más corto.
John Pang

Además, factorizar UIDevice.current.systemVersion.compare(version, options: .numeric)en un funcpuede ayudar a la lectura del código.
John Pang

5

Detalles

  • Xcode 10.2.1 (10E1001), Swift 5

Enlaces

OperatingSystemVersion

Solución

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
¿No hay problemas potenciales de redondeo cuando se usa Doublepara un número de versión, por ejemplo, en 10.0999lugar de 10.1?
mschmidt

No. var stringVersion = "10.0999"; print(stringVersion.toDouble!) // print 10.0999, se imprimirá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

y verifica como

if(iOS8)
{

}
else 
{
}  

4

La forma más fácil y sencilla de verificar la versión del sistema (y muchas otras versiones) en Swift 2 y superior es:

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

}

Además, con #availableusted puede verificar versiones de estos:

iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift

2

Mattt Thompson comparte una manera muy útil

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
}

Uso:

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

La respuesta de PS KVISH se tradujo a Swift 4.x con el cambio de nombre de las funciones, ya que específicamente estoy usando este fragmento para la aplicación iOS.


1

Nota: Disponible en iOS 8.0 y posterior. OS X v10.10 y posterior

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

Basado en la respuesta de Matt Thompson, aquí hay un método con pruebas de unidad respectivas que funciona con Swift y Objective-c en iOS 7 y superior (incluido iOS 9 que ya no le permite verificar el 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

te das cuenta de que el método real es muy corto y compacto y que acabo de agregar el código de prueba de la unidad para ilustración y prueba de que funciona, ¿verdad?
n8tr

Lamento no haberme dado cuenta de que es XCTest de un vistazo.
DawnSong

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

0

También si quieres consultar WatchOS.

Rápido

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

C objetivo

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

0

Obtenga la versión actual del sistema y divídalo. Para que pueda obtener la versión mayor y menor.

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

La mayoría de los códigos de muestra escritos aquí obtendrán resultados inesperados con versiones extra-cero. Por ejemplo,

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

Este método no devolverá verdadero con la versión aprobada "10.3.0" en iOS "10.3". Este tipo de resultado no tiene sentido y deben considerarse como la misma versión. Para obtener un resultado de comparación exacto, debemos considerar comparar todos los componentes numéricos en la cadena de versión. Además, proporcionar métodos globales en mayúsculas no es un buen camino a seguir. Como el tipo de versión que utilizamos en nuestro SDK es un String, tiene sentido ampliar la funcionalidad de comparación en String.

Para comparar la versión del sistema, todos los siguientes ejemplos deberían funcionar.

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

Puede consultarlo en mi repositorio aquí https://github.com/DragonCherry/VersionCompare

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.