Come controllare la versione iOS?


848

Voglio verificare se la iOSversione del dispositivo è superiore a quella che 3.1.3 ho provato cose come:

[[UIDevice currentDevice].systemVersion floatValue]

ma non funziona, voglio solo un:

if (version > 3.1.3) { }

Come posso raggiungere questo obiettivo?


5
Nota del moderatore : nel tempo, questa domanda ha accumulato oltre 30 risposte. Prima di aggiungere una nuova risposta, assicurarsi che la soluzione non sia già stata fornita.
Matt

3
Avvio di Xcode 7, if #available(iOS 9, *) {}in Swift. Avvio di Xcode 9, if (@available(iOS 11, *)) {}in obiettivo-c.
Cor

Risposte:


1002

La risposta rapida ...


A partire da Swift 2.0, è possibile utilizzare #availablein un ifo guardper proteggere il codice che dovrebbe essere eseguito solo su determinati sistemi.

if #available(iOS 9, *) {}


In Objective-C, è necessario verificare la versione del sistema ed eseguire un confronto.

[[NSProcessInfo processInfo] operatingSystemVersion] in iOS 8 e versioni successive.

A partire da Xcode 9:

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


La risposta completa ...

In Objective-C e Swift in rari casi, è meglio evitare di fare affidamento sulla versione del sistema operativo come indicazione delle funzionalità del dispositivo o del sistema operativo. Di solito esiste un metodo più affidabile per verificare se una particolare funzione o classe è disponibile.

Verifica della presenza di API:

Ad esempio, puoi verificare se UIPopoverControllerè disponibile sul dispositivo corrente usando NSClassFromString:

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

Per le classi debolmente collegate, è sicuro inviare un messaggio direttamente alla classe. In particolare, questo funziona per i framework che non sono esplicitamente collegati come "Richiesto". Per le classi mancanti, l'espressione restituisce zero, non riuscendo la condizione:

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

Alcune classi, come CLLocationManagere UIDevice, forniscono metodi per verificare le funzionalità del dispositivo:

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

Verifica della presenza di simboli:

Molto occasionalmente, è necessario verificare la presenza di una costante. Ciò è emerso in iOS 8 con l'introduzione di UIApplicationOpenSettingsURLString, utilizzato per caricare l'app Impostazioni tramite -openURL:. Il valore non esisteva prima di iOS 8. Il passaggio zero a questa API si arresterà in modo anomalo, quindi devi prima verificare l'esistenza della costante:

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

Confronto con la versione del sistema operativo:

Supponiamo che tu abbia di fronte la necessità relativamente rara di verificare la versione del sistema operativo. Per i progetti destinati a iOS 8 e versioni successive, NSProcessInfoinclude un metodo per eseguire confronti di versioni con meno possibilità di errore:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

I progetti destinati a sistemi meno recenti possono essere utilizzati systemVersionsu UIDevice. Apple lo utilizza nel proprio codice di esempio 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;
}

Se per qualsiasi motivo decidi che systemVersionè quello che vuoi, assicurati di trattarlo come una stringa o rischi di troncare il numero di revisione della patch (es. 3.1.2 -> 3.1).


161
Ci sono casi specifici in cui è garantito il controllo della versione del sistema. Ad esempio, un paio di classi e metodi che erano privati ​​n 3.x sono stati resi pubblici in 4.0, quindi se si verifica semplicemente la loro disponibilità si otterrà un risultato errato in 3.x. Inoltre, il modo in cui UIScrollViews gestisce le scale di zoom è cambiato sottilmente in 3.2 e versioni successive, quindi è necessario controllare le versioni del sistema operativo per elaborare i risultati in modo appropriato.
Brad Larson

2
iOS 3.2 non sembra inviare -viewWillAppeara UISplitViewController. Il mio trucco consiste nel determinare se <iOS 4.0 e inviarlo al controller Visualizzazione dettagli nella Root View -didSelectRowAtIndexPath.
JWW

10
Devi stare un po 'attento qui perché [@"10.0" compare:@"10" options:NSNumericSearch]ritorna NSOrderedDescending, che potrebbe non essere affatto inteso. (Potrei aspettarmi NSOrderedSame.) Questa è almeno una possibilità teorica.
SK9,

Sì, ho appena riscontrato un caso in cui un bug di iOS 5 doveva essere aggirato. respondsToSelectoret al non farebbero il lavoro - devono confrontare le versioni.
Hot Licks

2
Con l'introduzione di TVos questo è diventato ancora più importante. Vedi come TVos restituirà 9.0 mentre viene utilizzato l'SDK 9.1. Quindi controlla la classe o il metodo (selettore) è il modo migliore, dopo questo dovresti controllare NSFoundationVersionNumbere solo se ciò non è possibile dovresti controllare le versioni 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")) {
    ...
}

20
+1. Mantenere questo in un'intestazione che è possibile includere dove necessario è la soluzione più semplice che mi viene in mente. In molti casi questo è più affidabile del controllo della disponibilità utilizzando NSClassFromString. Un altro esempio è in iAd, dove se si utilizza ADBannerContentSizeIdentifierPortrait in una versione precedente alla 4.2 si otterrà EXEC_BAD_ACCESS, ma l'equivalente ADBannerContentSizeIdentifier320x50 è obsoleto dopo 4.1.
Rab,

1
Un altro posto che uso questo è con UIPageViewController e l'impostazione dello stile su UIPageViewControllerTransitionStyleScroll in iOS6.
Paul de Lange,

7
Questo non funziona per 10 secondi. Ad esempio, il confronto tra 4.10 e 4.9 darebbe il risultato sbagliato.
pzulw,

7
Bisogna stare molto attenti quando si usano .0numeri opzionali . Ad esempio, SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")fornisce risultati errati su iOS 7.0.
Yan,

1
Ho appena provato a inserirlo nel mio file .pch e funziona benissimo (costruendo almeno con Xcode 5)
whyoz

253

Come suggerito dai documenti ufficiali di Apple : è possibile utilizzare NSFoundationVersionNumber, dal NSObjCRuntime.hfile di intestazione.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}

40
+1 Questa è in effetti l' opzione più sicura e accurata qui.
mxcl,

8
Um .. NSFoundationVersionNumber_iOS_6_1non esiste in iOS 5 SDK.
Kjuly,

2
@Kjuly puoi definire tu stesso i numeri di versione mancanti: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (dai un'occhiata alla linea 102-130)
CarlJ

3
no, ti sbagli, NSFoundationVersionNumber_iOS_7_0 non esiste. Ma bene, potremmo definirlo con #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Per evitare un casino del genere, sono andato con la macro SYSTEM_VERSION_LESS_THAN (v) di yasirmturk
Cœur,

7
No, ma Apple aggiungerà il file NSFoundationVersionNumber_iOS_8_0iOS 9. Basta controllare NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ,

111

Avvio di Xcode 9, in Objective-C :

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

Avvio di Xcode 7, in Swift :

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

Per la versione, è possibile specificare MAJOR, MINOR o PATCH (vedere http://semver.org/ per le definizioni). Esempi:

  • iOS 11e iOS 11.0sono la stessa versione minima
  • iOS 10, iOS 10.3, iOS 10.3.1Sono diverse versioni minimali

È possibile inserire valori per uno di questi sistemi:

  • iOS, macOS, watchOS,tvOS

Esempio di caso reale tratto da uno dei miei pod :

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

documentazione


Come può essere invertito in Objective-C o Swift?
Legoless,

@Legolessif (...) {} else { ... }
Cœur

Posso usare guardin Objective-C invece di lasciare il blocco aperto e rientrare elsenell'istruzione?
Legoless,

@Legoless no, basta usare un ifblocco vuoto seguito da un else.
Cœur,

1
Questa è la soluzione che ho attualmente, volevo solo evitare inutili rientri e ifblocchi vuoti .
Legoless,

45

Questo è usato per verificare la versione SDK compatibile in Xcode, questo è se si dispone di un team di grandi dimensioni con diverse versioni di Xcode o più progetti che supportano SDK diversi che condividono lo stesso codice:

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

Quello che vuoi davvero è controllare la versione di iOS sul dispositivo. Puoi farlo con questo:

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

Versione rapida:

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
}

Le versioni correnti di swift dovrebbero usare questo:

if #available(iOS 12, *) {
    //iOS 12 specific code here
} else {
    //older than iOS 12 code here
}

37

Provare:

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
}

2
Perché non invertire l'ordine qui e salvare un confronto, poiché sia ​​@ "3.1.3" che systemVersion sono stringhe NSS? Vale a dire: `if ([@" 3.1.3 "confronta: [UIDevice currentDevice] .systemVersion opzioni: NSNumericSearch] == NSOrderedDescending); // versione del sistema operativo> = 3.1.3 altrimenti; // versione del sistema operativo <3.1.3`
Rob,

3
Ciò potrebbe rendere la logica meno chiara. L'operazione dovrebbe essere equivalente, tuttavia.
Jonathan Grynspan,

1
Un confronto tra due numeri interi non è sicuramente molto costoso.
KPM,

È davvero una questione di stile. Il sovraccarico dell'invio dei messaggi supererà di gran lunga il confronto dei numeri interi extra.
Jonathan Grynspan,

35

Approccio preferito

In Swift 2.0 Apple ha aggiunto il controllo della disponibilità utilizzando una sintassi molto più conveniente (Leggi di più qui ). Ora puoi controllare la versione del sistema operativo con una sintassi più pulita:

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

Questo è il preferito rispetto al controllo respondsToSelectorecc. ( Novità di Swift ). Ora il compilatore ti avviserà sempre se non stai proteggendo correttamente il tuo codice.


Pre Swift 2.0

Nuovo in iOS 8 è NSProcessInfo consentendo controlli di versione semantici migliori.

Distribuzione su iOS 8 e versioni successive

Per target minimi di distribuzione di iOS 8.0 o versioni successive, utilizzare NSProcessInfo operatingSystemVersiono isOperatingSystemAtLeastVersion.

Ciò produrrebbe quanto segue:

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

Distribuzione su iOS 7

Per destinazioni di distribuzione minime di iOS 7.1 o precedenti, utilizzare confronta con NSStringCompareOptions.NumericSearchon UIDevice systemVersion.

Ciò produrrebbe:

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

Altre letture su NSHipster .


9

Tengo sempre quelli nel mio file 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)

Grande. Meglio .pchmetterlo nel file del tuo progetto XCode
Vaibhav Jhaveri il

1
Metto tutte le mie costanti nel mio Constants.hfile che viene importato nel mio pchfile.
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;
  }


}

I periodi @Jef non sono punti decimali nel controllo delle versioni e sono rilevanti. La tua risposta non ignora i periodi, se non lo facesse fallirebbe. Nel controllo delle versioni ogni elemento separato da punto è un numero completo. Es .: '1.23.45' è maggiore di '1.2.345' poiché il secondo elemento '23' è maggiore di '2'. Se eliminassi i periodi sarebbe lo stesso numero.
Andres Canella,

6

Con la classe Version contenuta nel progetto nv-ios-version (Licenza Apache, Versione 2.0), è facile ottenere e confrontare la versione iOS. Un codice di esempio riportato di seguito scarica la versione iOS e verifica se la versione è maggiore o uguale 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.
}

Pagina del progetto: versione nv-ios TakahikoKawasaki / versione
nv-ios

Blog: Ottieni e confronta la versione iOS in fase di runtime con la classe Version
Ottieni e confronta la versione iOS in fase di runtime con la classe Version


5

Nuovo modo per verificare la versione del sistema usando swift Forget [[UIDevice currentDevice] systemVersion] e NSFoundationVersionNumber.

Possiamo usare NSProcessInfo -isOperatingSystemAtLeastVersion

     import Foundation

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

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

4

In generale è meglio chiedere se un oggetto può eseguire un determinato selettore, piuttosto che controllare un numero di versione per decidere se deve essere presente.

Quando questa non è un'opzione, devi stare un po 'attento qui perché [@"5.0" compare:@"5" options:NSNumericSearch]restituisce NSOrderedDescendingche potrebbe non essere affatto previsto; Potrei aspettarmi NSOrderedSamequi. Questa è almeno una preoccupazione teorica, a cui vale la pena difendersi a mio avviso.

Vale anche la pena considerare la possibilità di un input di versione errato che non può essere ragionevolmente confrontato. Apple ha alimenta le tre costanti predefinite NSOrderedAscending, NSOrderedSamee NSOrderedDescendingma posso pensare ad un uso per qualche cosa che si chiamaNSOrderedUnordered in caso non posso paragonare due cose e voglio restituire un valore che indica questo.

Inoltre, non è impossibile che Apple un giorno espanderà le sue tre costanti predefinite per consentire una varietà di valori di ritorno, facendo un confronto != NSOrderedAscendingpoco saggio.

Detto questo, considera il seguente codice.

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

4
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

Ovviamente, è NSFoundationVersionNumber_iOS_6_1necessario modificarlo in base alla versione iOS che si desidera verificare. Quello che ho scritto ora verrà probabilmente usato molto durante il test se un dispositivo esegue iOS7 o una versione precedente.


4

un po 'in ritardo alla festa, ma alla luce di iOS 8.0 là fuori questo potrebbe essere rilevante:

se puoi evitare di usarlo

[[UIDevice currentDevice] systemVersion]

Invece controlla l'esistenza di un metodo / classe / qualunque altra cosa.

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

Ho trovato utile per location manager dove devo chiamare requestWhenInUseAuthorization per iOS 8.0 ma il metodo non è disponibile per iOS <8


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

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

3

So che questa è una vecchia domanda, ma qualcuno avrebbe dovuto menzionare le macro in fase di compilazione in Availability.h. Tutti gli altri metodi qui sono soluzioni di runtime e non funzioneranno in un file di intestazione, categoria di classe o definizione di ivar.

Per queste situazioni, utilizzare

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

H / T questa risposta


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

Quindi aggiungere una condizione if come segue: -

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
   //Your code
}       

2

Esistono versioni come 7.0 o 6.0.3, quindi possiamo semplicemente convertire la versione in numeri per confrontarla. se la versione è come 7.0, aggiungi semplicemente un altro ".0" e prendi il suo valore numerico.

 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];

Per 6.0.0

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

per 7.0

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

semplicemente rimuovere i punti decimali è l'approccio sbagliato. considera un componente che ha più di 1 carattere, ad es 6.1.10. allora questo algoritmo produrrà 6110 > 700, il che non è corretto.
Ardnew,

Comprendo che Apple non è in grado di implementare nuove versioni, ma nella maggior parte dei casi il secondo numero della versione non è mai andato oltre 5, quindi 10 è fuori discussione. Questo è un approccio ad hoc, quindi se gestisce case per 2 componenti è possibile modificarlo per gestire quattro case aswel se si desidera eseguire manualmente. Ad ogni modo questo approccio è stato commentato al momento di iOS6 o 7. iOS 9 e 10 hanno modi molto migliori di controllarlo, cioè #available.
NaXir il

2

Prova il codice seguente:

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


1

Come variazione della soluzione yasimturks, ho definito una funzione e alcuni valori enum invece di cinque macro. Lo trovo più elegante, ma è una questione di gusti.

Uso:

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

File .h:

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

BOOL systemVersion(Comparison test, NSString* version);

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

Devi aggiungere il prefisso della tua app ai nomi, in particolare al Comparisontipo.


1

Utilizzando il modo consigliato di riferimento ... se non è presente alcuna definizione nei file di intestazione, è sempre possibile ottenere la versione stampandola su console con un dispositivo della versione IOS desiderata.

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

1

Soluzione per il controllo della versione iOS in 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")
}

Contro di questa soluzione: è semplicemente una cattiva pratica controllare i numeri di versione del sistema operativo, in qualunque modo lo si faccia. In questo modo non si dovrebbe mai stabilire il codice delle dipendenze, verificare sempre le caratteristiche, le capacità o l'esistenza di una classe. Considera questo; Apple potrebbe rilasciare una versione retrocompatibile di una classe, se lo facesse il codice che suggerisci non lo userebbe mai poiché la tua logica cerca un numero di versione del sistema operativo e NON l'esistenza della classe.

( Fonte di queste informazioni )

Soluzione per verificare l'esistenza della classe in Swift

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

Non utilizzarlo if (NSClassFromString("UIAlertController") == nil)perché funziona correttamente sul simulatore iOS utilizzando iOS 7.1 e 8.2, ma se esegui un test su un dispositivo reale utilizzando iOS 7.1, sfortunatamente noterai che non passerai mai attraverso l'altra parte dello snippet di codice.


Perché votare male? Questa soluzione funziona perfettamente utilizzando Swift e qualsiasi versione di iOS. Soprattutto il controllo dell'esistenza di classe è semplicemente perfetto.
Re-Wizard

1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)

0

Una versione più generica in Obj-C ++ 11 (probabilmente potresti sostituire alcune di queste cose con le funzioni NSString / C, ma questa è meno dettagliata. Questo ti dà due meccanismi. SplitSystemVersion ti offre un array di tutte le parti che è utile se vuoi solo attivare la versione principale (ad es switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }.).

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


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

float versionToBeCompared = 3.1.3;non può nemmeno compilare.
Provò il

0

Esempio rapido che funziona davvero:

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

Non usare NSProcessInfo perché non funziona con 8.0, quindi è praticamente inutile fino al 2016


0

Ecco una versione rapida:

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
}

Penso che la versione dovrebbe essere iOSVersion in linea 3-6 come 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.