¿Cómo verificar la versión de iOS?

848

Quiero verificar si la iOSversión del dispositivo es mayor de lo 3.1.3 que probé cosas como:

[[UIDevice currentDevice].systemVersion floatValue]

pero no funciona, solo quiero un:

if (version > 3.1.3) { }

¿Cómo puedo conseguir esto?

Juan
fuente
55
Nota para el moderador : Con el tiempo, esta pregunta ha acumulado más de 30 respuestas. Antes de agregar una nueva respuesta, asegúrese de que su solución aún no se haya proporcionado.
Matt
3
Iniciando Xcode 7, if #available(iOS 9, *) {}en Swift. Iniciando Xcode 9, if (@available(iOS 11, *)) {}en el objetivo-c.
Cœur

Respuestas:

1002

La respuesta rápida ...


A partir de Swift 2.0, se puede utilizar #availableen una ifo guardal código de protección que sólo se debe ejecutar en ciertos sistemas.

if #available(iOS 9, *) {}


En Objective-C, debe verificar la versión del sistema y realizar una comparación.

[[NSProcessInfo processInfo] operatingSystemVersion] en iOS 8 y superior.

A partir de Xcode 9:

if (@available(iOS 9, *)) {}


La respuesta completa ...

En Objective-C y Swift en casos raros, es mejor evitar confiar en la versión del sistema operativo como una indicación de las capacidades del dispositivo o del sistema operativo. Por lo general, hay un método más confiable para verificar si una característica o clase particular está disponible.

Comprobando la presencia de API:

Por ejemplo, puede verificar si UIPopoverControllerestá disponible en el dispositivo actual usando NSClassFromString:

if (NSClassFromString(@"UIPopoverController")) {
    // Do something
}

Para clases débilmente vinculadas, es seguro enviar mensajes a la clase, directamente. En particular, esto funciona para marcos que no están vinculados explícitamente como "Requerido". Para las clases que faltan, la expresión se evalúa como nula y falla la condición:

if ([LAContext class]) {
    // Do something
}

Algunas clases, como CLLocationManagery UIDevice, proporcionan métodos para verificar las capacidades del dispositivo:

if ([CLLocationManager headingAvailable]) {
    // Do something
}

Comprobando la presencia de símbolos:

Muy ocasionalmente, debe verificar la presencia de una constante. Esto surgió en iOS 8 con la introducción de UIApplicationOpenSettingsURLString, utilizado para cargar la aplicación de configuración a través de -openURL:. El valor no existía antes de iOS 8. Pasar nulo a esta API se bloqueará, por lo que primero debe asegurarse de verificar la existencia de la constante:

if (&UIApplicationOpenSettingsURLString != NULL) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}

Comparando con la versión del sistema operativo:

Supongamos que enfrenta la necesidad relativamente rara de verificar la versión del sistema operativo. Para proyectos dirigidos a iOS 8 y superior, NSProcessInfoincluye un método para realizar comparaciones de versiones con menos posibilidades de error:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Los proyectos dirigidos a sistemas más antiguos pueden usarse systemVersionen UIDevice. Apple lo usa en su código de muestra GLSprite .

// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) {
    displayLinkSupported = TRUE;
}

Si por alguna razón decide que systemVersiones lo que desea, asegúrese de tratarlo como una cadena o corre el riesgo de truncar el número de revisión del parche (por ejemplo, 3.1.2 -> 3.1).

Justin
fuente
161
Hay casos específicos en los que se justifica verificar la versión del sistema. Por ejemplo, un par de clases y métodos que eran privados n 3.x se hicieron públicos en 4.0, por lo que si simplemente verificaba su disponibilidad obtendría un resultado incorrecto en 3.x. Además, la forma en que UIScrollViews maneja las escalas de zoom cambió sutilmente en 3.2 y superiores, por lo que necesitaría verificar las versiones del sistema operativo para procesar los resultados adecuadamente.
Brad Larson
2
iOS 3.2 no parece enviar -viewWillAppearen a UISplitViewController. Mi truco es determinar si es <iOS 4.0, y enviarlo al Controlador de vista detallada yo mismo en la Vista raíz -didSelectRowAtIndexPath.
jww
10
Debe tener un poco de cuidado aquí porque los [@"10.0" compare:@"10" options:NSNumericSearch]retornos NSOrderedDescending, que bien podrían no ser intencionados. (Podría esperar NSOrderedSame). Esta es al menos una posibilidad teórica.
SK9
Sí, acabo de encontrar un caso en el que se debe evitar un error de iOS 5. respondsToSelectoret al no harían el trabajo, tienen que comparar versiones.
Hot Licks
2
Con la introducción de TVos, esto se ha vuelto aún más importante. Ver como TVos devolverá 9.0 mientras se usa el SDK 9.1. Por lo tanto, verificar la clase o el método (selector) es la mejor manera, después de esto, debe verificar el NSFoundationVersionNumbery solo si eso no es posible, debe verificar las versiones del sistema UIDevice.
rckoenes
1055
/*
 *  System Versioning Preprocessor Macros
 */ 

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

/*
 *  Usage
 */ 

if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {
    ...
}

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
    ...
}
yasirmturk
fuente
20
+1. Mantener esto en un encabezado que puede incluir donde sea necesario es la solución más fácil que se me ocurre. En varios casos, esto es más confiable que verificar la disponibilidad utilizando NSClassFromString. Otro ejemplo es en iAd, donde si usa ADBannerContentSizeIdentifierPortrait en una versión anterior a 4.2 obtendrá EXEC_BAD_ACCESS, pero el ADBannerContentSizeIdentifier320x50 equivalente queda obsoleto después de 4.1.
Rab
1
Otro lugar donde uso esto es con UIPageViewController y configurando el estilo en UIPageViewControllerTransitionStyleScroll en iOS6.
Paul de Lange
77
Esto no funciona durante 10 segundos. Por ejemplo, comparar 4.10 y 4.9 daría un resultado incorrecto.
pzulw
77
Se debe tener mucho cuidado al usar .0números opcionales . Por ejemplo, SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")da un resultado incorrecto en iOS 7.0.
Yan
1
Acabo de probar poner esto en mi archivo .pch y funciona muy bien (compilando con Xcode 5 al menos)
whyoz
253

Según lo sugerido por los documentos oficiales de Apple : puede usar NSFoundationVersionNumber, desde el NSObjCRuntime.harchivo de encabezado.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}
CarlJ
fuente
40
+1 Esta es, de hecho, la opción más segura y precisa aquí.
mxcl
8
Um .. NSFoundationVersionNumber_iOS_6_1no existe en iOS 5 SDK.
Kjuly
2
@Kjuly puedes definir los números de versión que faltan por ti mismo: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (mira la línea 102-130)
CarlJ
3
no, te equivocas, NSFoundationVersionNumber_iOS_7_0 no existe. Pero bueno, podríamos definirlo con #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Para evitar jugar así, fui con la macro SYSTEM_VERSION_LESS_THAN (v) de yasirmturk
Cœur el
77
no, pero Apple agregará el NSFoundationVersionNumber_iOS_8_0en iOS 9. solo busca NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ
111

Iniciando Xcode 9, en Objective-C :

if (@available(iOS 11, *)) {
    // iOS 11 (or newer) ObjC code
} else {
    // iOS 10 or older code
}

Iniciando Xcode 7, en Swift :

if #available(iOS 11, *) {
    // iOS 11 (or newer) Swift code
} else {
    // iOS 10 or older code
}

Para la versión, puede especificar el MAYOR, el MENOR o el PARCHE (consulte http://semver.org/ para ver las definiciones). Ejemplos:

  • iOS 11y iOS 11.0son la misma versión mínima
  • iOS 10, iOS 10.3, iOS 10.3.1Son diferentes versiones mínimas

Puede ingresar valores para cualquiera de esos sistemas:

  • iOS, macOS, watchOS,tvOS

Ejemplo de caso real tomado de uno de mis pods :

if #available(iOS 10.0, tvOS 10.0, *) {
    // iOS 10+ and tvOS 10+ Swift code
} else {
    // iOS 9 and tvOS 9 older code
}

documentación

Coeur
fuente
¿Cómo se puede invertir esto en Objective-C o Swift?
Legoless
@Legolessif (...) {} else { ... }
Cœur
¿Puedo usar guarden Objective-C en lugar de dejar el bloque abierto y sangrar en la elsedeclaración?
Legoless
@Legoless no, solo usa un ifbloque vacío seguido de un else.
Cœur
1
Esa es la solución que tengo actualmente, solo quería evitar sangría innecesaria y ifbloques vacíos .
Legoless
45

Esto se usa para verificar la versión de SDK compatible en Xcode, esto es si tiene un equipo grande con diferentes versiones de Xcode o múltiples proyectos que admiten diferentes SDK que comparten el mismo código:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
  //programming in iOS 8+ SDK here
#else
  //programming in lower than iOS 8 here   
#endif

Lo que realmente desea es verificar la versión de iOS en el dispositivo. Puedes hacer eso con esto:

if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
  //older than iOS 8 code here
} else {
  //iOS 8 specific code here
}

Versión rápida:

if let version = Float(UIDevice.current.systemVersion), version < 9.3 {
    //add lower than 9.3 code here
} else {
    //add 9.3 and above code here
}

Las versiones actuales de swift deberían usar esto:

if #available(iOS 12, *) {
    //iOS 12 specific code here
} else {
    //older than iOS 12 code here
}
Travis M.
fuente
37

Tratar:

NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"3.1.3" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending) {
    // OS version >= 3.1.3
} else {
    // OS version < 3.1.3
}
Jonathan Grynspan
fuente
2
¿Por qué no invertir el orden aquí y guardar una comparación, ya que tanto @ "3.1.3" como systemVersion son NSStrings? Es decir: `if ([@" 3.1.3 "compare: [UIDevice currentDevice] .systemVersion opciones: NSNumericSearch] == NSOrderedDescending); // Versión del sistema operativo> = 3.1.3 más; // Versión del sistema operativo <3.1.3`
Rob
3
Hacer eso puede hacer que la lógica sea menos clara. Sin embargo, la operación debería ser equivalente.
Jonathan Grynspan
1
Una comparación entre dos enteros seguramente no es muy costosa.
KPM
Es realmente una cuestión de estilo. La sobrecarga del envío de mensajes superará ampliamente la comparación de enteros adicionales.
Jonathan Grynspan
35

Enfoque preferido

En Swift 2.0, Apple agregó la verificación de disponibilidad utilizando una sintaxis mucho más conveniente (Lea más aquí ). Ahora puede verificar la versión del sistema operativo con una sintaxis más limpia:

if #available(iOS 9, *) {
    // Then we are on iOS 9
} else {
    // iOS 8 or earlier
}

Este es el preferido sobre la comprobación, respondsToSelectoretc. ( Novedades de Swift ). Ahora el compilador siempre te avisará si no estás protegiendo tu código correctamente.


Pre Swift 2.0

Nuevo en iOS 8 está NSProcessInfopermitiendo mejores controles de versiones semánticas.

Implementación en iOS 8 y superior

Para objetivos mínimos de implementación de iOS 8.0 o superior, use NSProcessInfo operatingSystemVersiono isOperatingSystemAtLeastVersion.

Esto produciría lo siguiente:

let minimumVersion = NSOperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2)
if NSProcessInfo().isOperatingSystemAtLeastVersion(minimumVersion) {
    //current version is >= (8.1.2)
} else {
    //current version is < (8.1.2)
}

Implementación en iOS 7

Para objetivos de implementación mínimos de iOS 7.1 o inferior, use compare con NSStringCompareOptions.NumericSearchon UIDevice systemVersion.

Esto produciría:

let minimumVersionString = "3.1.3"
let versionComparison = UIDevice.currentDevice().systemVersion.compare(minimumVersionString, options: .NumericSearch)
switch versionComparison {
    case .OrderedSame, .OrderedDescending:
        //current version is >= (3.1.3)
        break
    case .OrderedAscending:
        //current version is < (3.1.3)
        fallthrough
    default:
        break;
}

Más lectura en NSHipster .

Daniel Galasko
fuente
9

Siempre los guardo en mi archivo Constants.h:

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES) 
#define IS_OS_5_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)
#define IS_OS_6_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
#define IS_OS_8_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
Segev
fuente
Excelente. Es mejor colocar esto en el .pcharchivo de su proyecto XCode
Vaibhav Jhaveri
1
Coloco todas mis constantes en mi Constants.harchivo que se importa en mi pcharchivo.
Segev
6
+(BOOL)doesSystemVersionMeetRequirement:(NSString *)minRequirement{

// eg  NSString *reqSysVer = @"4.0";


  NSString *currSysVer = [[UIDevice currentDevice] systemVersion];

  if ([currSysVer compare:minRequirement options:NSNumericSearch] != NSOrderedAscending)
  {
    return YES;
  }else{
    return NO;
  }


}
Jef
fuente
Los períodos @Jef no son puntos decimales en el control de versiones y son relevantes. Su respuesta no ignora los períodos, fallaría si lo hiciera. En el control de versiones, cada elemento separado por puntos es un número completo. Ej: '1.23.45' es mayor que '1.2.345' ya que el segundo elemento '23' es mayor que '2'. Si eliminara los períodos, sería el mismo número.
Andres Canella
6

Con la clase Version que se incluye en el proyecto nv-ios-version (Apache License, Version 2.0), es fácil obtener y comparar la versión de iOS. Un código de ejemplo a continuación volca la versión de iOS y verifica si la versión es mayor o igual a 6.0.

// Get the system version of iOS at runtime.
NSString *versionString = [[UIDevice currentDevice] systemVersion];

// Convert the version string to a Version instance.
Version *version = [Version versionWithString:versionString];

// Dump the major, minor and micro version numbers.
NSLog(@"version = [%d, %d, %d]",
    version.major, version.minor, version.micro);

// Check whether the version is greater than or equal to 6.0.
if ([version isGreaterThanOrEqualToMajor:6 minor:0])
{
    // The iOS version is greater than or equal to 6.0.
}

// Another way to check whether iOS version is
// greater than or equal to 6.0.
if (6 <= version.major)
{
    // The iOS version is greater than or equal to 6.0.
}

Página del proyecto: nv-ios-version
TakahikoKawasaki / nv-ios-version

Blog: Obtenga y compare la versión de iOS en tiempo de ejecución con la clase Versión
Obtenga y compare la versión de iOS en tiempo de ejecución con la clase Versión

Takahiko Kawasaki
fuente
5

Nueva forma de verificar la versión del sistema utilizando el rápido Forget [[UIDevice currentDevice] systemVersion] y NSFoundationVersionNumber.

Podemos usar NSProcessInfo -isOperatingSystemAtLeastVersion

     import Foundation

     let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
     NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
Govind
fuente
5

UIDevice + IOSVersion.h

@interface UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion

@end

UIDevice + IOSVersion.m

#import "UIDevice+IOSVersion.h"

@implementation UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedSame;
}

+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedDescending;
}

+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedDescending;
}

@end
Oliver Pearmain
fuente
4

En general, es mejor preguntar si un objeto puede realizar un selector dado, en lugar de verificar un número de versión para decidir si debe estar presente.

Cuando esto no es una opción, debe tener un poco de cuidado aquí porque las [@"5.0" compare:@"5" options:NSNumericSearch]devoluciones NSOrderedDescendingpodrían no ser intencionadas; Podría esperar NSOrderedSameaquí. Esto es al menos una preocupación teórica, una que vale la pena defender en mi opinión.

También vale la pena considerar la posibilidad de una entrada de versión incorrecta con la que no se puede comparar razonablemente. Manzana suministra las tres constantes predefinidas NSOrderedAscending, NSOrderedSamey NSOrderedDescendingaunque no puedo pensar en un uso para alguna cosa que se llama NSOrderedUnordereden el caso de que no puedo comparar dos cosas y quiero devolver un valor que indica esto.

Además, no es imposible que Apple algún día expanda sus tres constantes predefinidas para permitir una variedad de valores de retorno, haciendo una comparación != NSOrderedAscendingimprudente.

Dicho esto, considere el siguiente código.

typedef enum {kSKOrderedNotOrdered = -2, kSKOrderedAscending = -1, kSKOrderedSame = 0, kSKOrderedDescending = 1} SKComparisonResult;

@interface SKComparator : NSObject
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo;
@end

@implementation SKComparator
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo {
  if (!vOne || !vTwo || [vOne length] < 1 || [vTwo length] < 1 || [vOne rangeOfString:@".."].location != NSNotFound ||
    [vTwo rangeOfString:@".."].location != NSNotFound) {
    return SKOrderedNotOrdered;
  }
  NSCharacterSet *numericalCharSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
  NSString *vOneTrimmed = [vOne stringByTrimmingCharactersInSet:numericalCharSet];
  NSString *vTwoTrimmed = [vTwo stringByTrimmingCharactersInSet:numericalCharSet];
  if ([vOneTrimmed length] > 0 || [vTwoTrimmed length] > 0) {
    return SKOrderedNotOrdered;
  }
  NSArray *vOneArray = [vOne componentsSeparatedByString:@"."];
  NSArray *vTwoArray = [vTwo componentsSeparatedByString:@"."];
  for (NSUInteger i = 0; i < MIN([vOneArray count], [vTwoArray count]); i++) {
    NSInteger vOneInt = [[vOneArray objectAtIndex:i] intValue];
    NSInteger vTwoInt = [[vTwoArray objectAtIndex:i] intValue];
    if (vOneInt > vTwoInt) {
      return kSKOrderedDescending;
    } else if (vOneInt < vTwoInt) {
      return kSKOrderedAscending;
    }
  }
  if ([vOneArray count] > [vTwoArray count]) {
    for (NSUInteger i = [vTwoArray count]; i < [vOneArray count]; i++) {
      if ([[vOneArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedDescending;
      }
    }
  } else if ([vOneArray count] < [vTwoArray count]) {
    for (NSUInteger i = [vOneArray count]; i < [vTwoArray count]; i++) {
      if ([[vTwoArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedAscending;
      }
    }
  }
  return kSKOrderedSame;
}
@end
SK9
fuente
4
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

Donde, por supuesto, NSFoundationVersionNumber_iOS_6_1debe cambiarse según corresponda para la versión de iOS que desea verificar. Lo que he escrito probablemente se usará mucho al probar si un dispositivo ejecuta iOS7 o una versión anterior.

OscarWyck
fuente
4

un poco tarde para la fiesta, pero a la luz de iOS 8.0, esto podría ser relevante:

si puedes evitar usar

[[UIDevice currentDevice] systemVersion]

En su lugar, verifique la existencia de un método / clase / lo que sea.

if ([self.yourClassInstance respondsToSelector:@selector(<yourMethod>)]) 
{ 
    //do stuff 
}

Me pareció útil para el administrador de ubicaciones donde tengo que llamar a requestWhenInUseAuthorization para iOS 8.0 pero el método no está disponible para iOS <8

Denis Kanygin
fuente
3
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

if (_kisiOS7) {
            NSLog(@"iOS7 or greater")
} 
else {
           NSLog(@"Less than iOS7");
}
Gaurav Gilani
fuente
3

Sé que esta es una vieja pregunta, pero alguien debería haber mencionado las macros en tiempo de compilación Availability.h. Todos los demás métodos aquí son soluciones de tiempo de ejecución, y no funcionarán en un archivo de encabezado, categoría de clase o definición de ivar.

Para estas situaciones, use

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_6_0
  // iOS 6+ code here
#else
  // Pre iOS 6 code here
#endif

h / t esta respuesta

bcattle
fuente
3
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Luego agregue una condición if de la siguiente manera: -

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
   //Your code
}       
Sumit Kumar Saha
fuente
2

Hay versiones como 7.0 o 6.0.3, por lo que simplemente podemos convertir la versión en números para comparar. si la versión es como 7.0, simplemente agregue otro ".0" y luego tome su valor numérico.

 int version;
 NSString* iosVersion=[[UIDevice currentDevice] systemVersion];
 NSArray* components=[iosVersion componentsSeparatedByString:@"."];
 if ([components count]==2) {
    iosVersion=[NSString stringWithFormat:@"%@.0",iosVersion];

 }
 iosVersion=[iosVersion stringByReplacingOccurrencesOfString:@"." withString:@""];
 version=[iosVersion integerValue];

Para 6.0.0

  if (version==600) {
    // Do something
  }

para 7.0

 if (version==700) {
   // Do something
 }
NaXir
fuente
simplemente eliminar los puntos decimales es el enfoque equivocado. considere un componente que tiene más de 1 carácter, por ejemplo 6.1.10. entonces este algoritmo rendirá 6110 > 700, lo cual no es correcto.
ardnew
Entiendo que Apple es malo para lanzar nuevas versiones, pero en la mayoría de los casos el segundo número de la versión nunca fue más allá de 5, por lo que 10 está fuera de discusión. Este es un enfoque adhoc, por lo que si maneja mayúsculas y minúsculas para 2 componentes, puede modificarlo para manejar cuatro mayúsculas y minúsculas si lo desea de forma manual. De todos modos, este enfoque se comentó en el momento de iOS6 o 7. iOS 9 y 10 tienen formas mucho mejores de verificarlo, es decir, #disponible.
NaXir
2

Prueba el siguiente código:

NSString *versionString = [[UIDevice currentDevice] systemVersion];
annu
fuente
2

Solo para recuperar el valor de cadena de la versión del sistema operativo:

[[UIDevice currentDevice] systemVersion]
Javier Calatrava Llavería
fuente
1

Como una variación de la solución yasimturks, definí una función y algunos valores de enumeración en lugar de cinco macros. Me parece más elegante, pero eso es cuestión de gustos.

Uso:

if (systemVersion(LessThan, @"5.0")) ...

archivo .h:

typedef enum {
  LessThan,
  LessOrEqual,
  Equal,
  GreaterOrEqual,
  GreaterThan,
  NotEqual
} Comparison;

BOOL systemVersion(Comparison test, NSString* version);

archivo .m:

BOOL systemVersion(Comparison test, NSString* version) {
  NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare: version options: NSNumericSearch];
  switch (test) {
    case LessThan:       return result == NSOrderedAscending;
    case LessOrEqual:    return result != NSOrderedDescending;
    case Equal:          return result == NSOrderedSame;
    case GreaterOrEqual: return result != NSOrderedAscending;
    case GreaterThan:    return result == NSOrderedDescending;
    case NotEqual:       return result != NSOrderedSame;
  }
}

Debe agregar el prefijo de su aplicación a los nombres, especialmente al Comparisontipo.

jcsahnwaldt dice GoFundMonica
fuente
1

Utilizando la forma recomendada recomendada ... si no hay una definición en los archivos de encabezado, siempre puede obtener la versión imprimiéndola en la consola con un dispositivo de la versión IOS deseada.

- (BOOL) isIOS8OrAbove{
    float version802 = 1140.109985;
    float version8= 1139.100000; // there is no def like NSFoundationVersionNumber_iOS_7_1 for ios 8 yet?
    NSLog(@"la version actual es [%f]", NSFoundationVersionNumber);
    if (NSFoundationVersionNumber >= version8){
        return true;
    }
    return false;
}
tyoc213
fuente
1

Solución para verificar la versión de iOS en Swift

switch (UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)) {
    case .OrderedAscending:
       println("iOS < 8.0")

    case .OrderedSame, .OrderedDescending:
       println("iOS >= 8.0")
}

Contras de esta solución: es simplemente una mala práctica verificar los números de versión del sistema operativo, de cualquier manera que lo haga. Uno nunca debe codificar las dependencias de esta manera, siempre verificar las características, capacidades o la existencia de una clase. Considera esto; Apple puede lanzar una versión de una clase compatible con versiones anteriores, si lo hicieran, el código que sugiera nunca lo usaría ya que su lógica busca un número de versión del sistema operativo y NO la existencia de la clase.

( Fuente de esta información )

Solución para verificar la existencia de clases en Swift

if (objc_getClass("UIAlertController") == nil) {
   // iOS 7
} else {
   // iOS 8+
}

No lo use if (NSClassFromString("UIAlertController") == nil)porque funciona correctamente en el simulador de iOS con iOS 7.1 y 8.2, pero si prueba en un dispositivo real con iOS 7.1, lamentablemente notará que nunca pasará por la parte más del fragmento de código.

Rey Mago
fuente
¿Por qué votar abajo? Esta solución funciona perfectamente con Swift y cualquier versión de iOS. Especialmente la comprobación de la existencia de la clase es simplemente perfecta.
King-Wizard
1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
Gank
fuente
0

Una versión más genérica en Obj-C ++ 11 (probablemente podría reemplazar algunas de estas cosas con las funciones NSString / C, pero esto es menos detallado. Esto le brinda dos mecanismos. SplitSystemVersion le brinda una matriz de todas las partes que es útil si solo desea activar la versión principal (p switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }. ej .).

#include <boost/lexical_cast.hpp>

- (std::vector<int>) splitSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    std::vector<int> versions;
    auto i = version.begin();

    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        versions.push_back(boost::lexical_cast<int>(versionPart));
    }

    return versions;
}

/** Losslessly parse system version into a number
 * @return <0>: the version as a number,
 * @return <1>: how many numeric parts went into the composed number. e.g.
 * X.Y.Z = 3.  You need this to know how to compare again <0>
 */
- (std::tuple<int, int>) parseSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    return {versionAsNumber, nParts};
}


/** Assume that the system version will not go beyond X.Y.Z.W format.
 * @return The version string.
 */
- (int) parseSystemVersionAlt {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end() && nParts < 4) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    // don't forget to pad as systemVersion may have less parts (i.e. X.Y).
    for (; nParts < 4; nParts++) {
        versionAsNumber *= 100;
    }

    return versionAsNumber;
}
Vitali
fuente
0

Prueba esto

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { 
// do some work
}
Muhammad Aamir Ali
fuente
Explica qué hace esto.
Kevin Panko
si verificará si la versión del sistema operativo es iOS 7 o no
Muhammad Aamir Ali
0
float deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
float versionToBeCompared = 3.1.3; //(For Example in your case)

if(deviceOSVersion < versionToBeCompared)
   //Do whatever you need to do. Device version is lesser than 3.1.3(in your case)
else 
   //Device version should be either equal to the version you specified or above
GJDK
fuente
float versionToBeCompared = 3.1.3;Ni siquiera puedo compilar.
Pang
0

Ejemplo rápido que realmente funciona:

switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
case .OrderedSame, .OrderedDescending:
    println("iOS >= 8.0")
case .OrderedAscending:
    println("iOS < 8.0")
}

No use NSProcessInfo porque no funciona con 8.0, por lo que es prácticamente inútil hasta 2016

Esqarrouth
fuente
0

Aquí hay una versión rápida:

struct iOSVersion {
    static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue
    static let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)
    static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)
    static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
}

Uso:

if iOSVersion.iOS8 {
    //Do iOS8 code here
}
Swinny89
fuente
Creo que la versión debería ser iOSVersion en la línea 3-6 como struct iOSVersion { static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue static let iOS7 = (iOSVersion.SYS_VERSION_FLOAT < 8.0 && iOSVersion.SYS_VERSION_FLOAT >= 7.0) static let iOS8 = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0) static let iOS9 = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0) }
Kastor