Wie überprüfe ich die iOS-Version?

848

Ich möchte überprüfen, ob die iOSVersion des Geräts größer ist, als 3.1.3 ich versucht habe:

[[UIDevice currentDevice].systemVersion floatValue]

aber es funktioniert nicht, ich will nur ein:

if (version > 3.1.3) { }

Wie kann ich das erreichen?

John
quelle
5
Moderator Hinweis : Im Laufe der Zeit hat diese Frage über 30 Antworten erhalten. Stellen Sie vor dem Hinzufügen einer neuen Antwort sicher, dass Ihre Lösung noch nicht bereitgestellt wurde.
Matt
3
Starten von Xcode 7 if #available(iOS 9, *) {}in Swift. Starten von Xcode 9 if (@available(iOS 11, *)) {}in Ziel-c.
Cœur
Überprüfen Sie diese github.com/aleemrazzaq/ARCompactDeviceInfo
Aleem

Antworten:

1002

Die schnelle Antwort…


Ab Swift 2.0 können Sie #availablein einem ifoder guardzum Schutz von Code verwenden, der nur auf bestimmten Systemen ausgeführt werden sollte.

if #available(iOS 9, *) {}


In Objective-C müssen Sie die Systemversion überprüfen und einen Vergleich durchführen.

[[NSProcessInfo processInfo] operatingSystemVersion] in iOS 8 und höher.

Ab Xcode 9:

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


Die vollständige Antwort…

In Objective-C und in seltenen Fällen in Swift ist es besser, sich nicht auf die Betriebssystemversion als Hinweis auf Geräte- oder Betriebssystemfunktionen zu verlassen. Es gibt normalerweise eine zuverlässigere Methode, um zu überprüfen, ob ein bestimmtes Feature oder eine bestimmte Klasse verfügbar ist.

Überprüfen, ob APIs vorhanden sind:

Sie können beispielsweise überprüfen, ob UIPopoverControllerauf dem aktuellen Gerät Folgendes verfügbar ist NSClassFromString:

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

Bei schwach verknüpften Klassen ist es sicher, die Klasse direkt zu benachrichtigen. Dies funktioniert insbesondere für Frameworks, die nicht explizit als "Erforderlich" verknüpft sind. Bei fehlenden Klassen wird der Ausdruck mit Null ausgewertet, wobei die Bedingung nicht erfüllt wird:

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

Einige Klassen, wie CLLocationManagerund UIDevice, bieten Methoden zum Überprüfen der Gerätefunktionen:

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

Überprüfen, ob Symbole vorhanden sind:

Sehr gelegentlich müssen Sie prüfen, ob eine Konstante vorhanden ist. Dies kam in iOS 8 mit der Einführung von UIApplicationOpenSettingsURLString, verwendet, um Einstellungen App über zu laden -openURL:. Der Wert war vor iOS 8 nicht vorhanden. Wenn Sie nil an diese API übergeben, stürzt dies ab. Überprüfen Sie daher zunächst, ob die Konstante vorhanden ist:

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

Vergleich mit der Betriebssystemversion:

Nehmen wir an, Sie sehen sich mit der relativ seltenen Notwendigkeit konfrontiert, die Betriebssystemversion zu überprüfen. NSProcessInfoEnthält für Projekte mit iOS 8 und höher eine Methode zum Durchführen von Versionsvergleichen mit geringerer Fehlerwahrscheinlichkeit:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Projekte, die auf ältere Systeme abzielen, können systemVersionauf verwendet werden UIDevice. Apple verwendet es in seinem GLSprite- Beispielcode.

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

Wenn Sie aus irgendeinem Grund entscheiden, dass dies das systemVersionist, was Sie möchten, stellen Sie sicher , dass Sie es als Zeichenfolge behandeln, da sonst die Patch-Versionsnummer abgeschnitten werden kann (z. B. 3.1.2 -> 3.1).

Justin
quelle
161
In bestimmten Fällen ist die Überprüfung der Systemversion erforderlich. Zum Beispiel wurden einige Klassen und Methoden, die privat n 3.x waren, in 4.0 veröffentlicht. Wenn Sie also einfach die Verfügbarkeit überprüfen, erhalten Sie in 3.x ein falsches Ergebnis. Darüber hinaus hat sich die Art und Weise, wie UIScrollViews mit Zoomskalen umgehen, in Version 3.2 und höher geringfügig geändert. Daher müssten Sie die Betriebssystemversionen überprüfen, um die Ergebnisse ordnungsgemäß zu verarbeiten.
Brad Larson
2
iOS 3.2 scheint nicht zu senden , -viewWillAppearin ein UISplitViewController. Mein Hack besteht darin, festzustellen, ob <iOS 4.0, und es selbst in der Stammansicht an den Detail View Controller zu senden -didSelectRowAtIndexPath.
JWW
10
Sie müssen hier etwas vorsichtig sein, da [@"10.0" compare:@"10" options:NSNumericSearch]Rückgaben NSOrderedDescending, die möglicherweise überhaupt nicht beabsichtigt sind. (Ich könnte erwarten NSOrderedSame.) Dies ist zumindest eine theoretische Möglichkeit.
SK9
Ja, ich bin gerade auf einen Fall gestoßen, in dem ein iOS 5-Fehler umgangen werden musste. respondsToSelectoret al würden den Job nicht machen - müssen Versionen vergleichen.
Hot Licks
2
Mit der Einführung von TVos ist dies noch wichtiger geworden. Da TVos 9.0 zurückgibt, während das 9.1 SDK verwendet wird. Überprüfen Sie also, ob die Klasse oder Methode (Selektor) der beste Weg ist. Danach sollten Sie die überprüfen NSFoundationVersionNumberund nur dann, wenn dies nicht möglich ist, die Systemversionen aktivieren 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
quelle
20
+1. Dies in einem Header zu speichern, den Sie bei Bedarf einfügen können, ist die einfachste Lösung, die ich mir vorstellen kann. In einigen Fällen ist dies zuverlässiger als die Überprüfung der Verfügbarkeit mit NSClassFromString. Ein weiteres Beispiel ist iAd. Wenn Sie ADBannerContentSizeIdentifierPortrait in einer Version vor 4.2 verwenden, erhalten Sie EXEC_BAD_ACCESS, aber das entsprechende ADBannerContentSizeIdentifier320x50 ist nach 4.1 veraltet.
Rab
1
Ein anderer Ort, an dem ich dies verwende, ist UIPageViewController und das Setzen des Stils auf UIPageViewControllerTransitionStyleScroll in iOS6.
Paul de Lange
7
Dies funktioniert nicht für 10s. Zum Beispiel würde ein Vergleich von 4.10 und 4.9 das falsche Ergebnis ergeben.
Pzulw
7
Man sollte sehr vorsichtig sein, wenn man optionale .0Nummern verwendet. Gibt zum Beispiel SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")unter iOS 7.0 ein falsches Ergebnis.
Yan
1
Ich habe gerade getestet, wie ich das in meine .pch-Datei eingefügt habe, und es funktioniert großartig (mindestens mit Xcode 5)
whyoz
253

Wie in den offiziellen Apple-Dokumenten vorgeschlagen : Sie können die NSFoundationVersionNumberaus der NSObjCRuntime.hHeader-Datei verwenden.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}
CarlJ
quelle
40
+1 Dies ist in der Tat die sicherste und genaueste Option hier.
mxcl
8
Ähm .. NSFoundationVersionNumber_iOS_6_1existiert nicht im iOS 5 SDK.
Juli
2
@ Juli können Sie die fehlenden Versionsnummern selbst definieren: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (siehe Zeile 102-130)
CarlJ
3
Nein, Sie liegen falsch. NSFoundationVersionNumber_iOS_7_0 existiert nicht. Aber gut, wir könnten es mit definieren #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Um solche Probleme zu vermeiden, habe ich das Makro SYSTEM_VERSION_LESS_THAN (v) von yasirmturk
Cœur
7
Nein, aber Apple wird das NSFoundationVersionNumber_iOS_8_0in iOS 9 hinzufügen . Nur nach NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ
111

Starten von Xcode 9 in Ziel-C :

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

Starten von Xcode 7 in Swift :

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

Für die Version können Sie MAJOR, MINOR oder PATCH angeben ( Definitionen siehe http://semver.org/ ). Beispiele:

  • iOS 11und iOS 11.0sind die gleiche minimale Version
  • iOS 10, iOS 10.3, iOS 10.3.1Sind verschiedene Versionen minimal

Sie können Werte für jedes dieser Systeme eingeben:

  • iOS, macOS, watchOS,tvOS

Ein echtes Fallbeispiel aus einem meiner Pods :

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

Dokumentation

Cœur
quelle
Wie kann dies in Objective-C oder Swift invertiert werden?
Legoless
@ Legolessif (...) {} else { ... }
Cœur
Kann ich guardin Objective-C verwenden, anstatt den Block offen zu lassen und in der elseAnweisung einzurücken ?
Legoless
@Legoless nein, benutze einfach einen leeren ifBlock gefolgt von einem else.
Cœur
1
Das ist die Lösung, die ich derzeit habe. Ich wollte nur unnötige Einrückungen und leere ifBlöcke vermeiden .
Legoless
45

Dies wird verwendet, um in Xcode nach kompatiblen SDK-Versionen zu suchen. Dies ist der Fall, wenn Sie ein großes Team mit unterschiedlichen Xcode-Versionen oder mehrere Projekte haben, die unterschiedliche SDKs unterstützen, die denselben Code verwenden:

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

Was Sie wirklich wollen, ist die iOS-Version auf dem Gerät zu überprüfen. Das können Sie damit machen:

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

Schnelle Version:

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
}

Aktuelle Versionen von swift sollten Folgendes verwenden:

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

Versuchen:

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
quelle
2
Warum nicht die Reihenfolge hier umkehren und einen Vergleich speichern, da sowohl @ "3.1.3" als auch systemVersion NSStrings sind? Dh: `if ([@" 3.1.3 "vergleiche: [UIDevice currentDevice] .systemVersion-Optionen: NSNumericSearch] == NSOrderedDescending); // Betriebssystemversion> = 3.1.3 else; // Betriebssystemversion <3.1.3`
Rob
3
Dadurch wird die Logik möglicherweise weniger klar. Die Operation sollte jedoch gleichwertig sein.
Jonathan Grynspan
1
Ein Vergleich zwischen zwei ganzen Zahlen ist sicherlich nicht sehr teuer.
KPM
Es ist wirklich eine Frage des Stils. Der Overhead des Nachrichtenversands überwiegt den zusätzlichen Ganzzahlvergleich bei weitem.
Jonathan Grynspan
35

Bevorzugter Ansatz

In Swift 2.0 hat Apple die Verfügbarkeitsprüfung mithilfe einer weitaus bequemeren Syntax hinzugefügt (Lesen Sie hier mehr ). Jetzt können Sie die Betriebssystemversion mit einer saubereren Syntax überprüfen:

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

Dies ist die bevorzugte Prüfung respondsToSelectorusw. ( Was ist neu in Swift? ). Jetzt warnt Sie der Compiler immer, wenn Sie Ihren Code nicht richtig schützen.


Pre Swift 2.0

Neu in iOS 8 ist NSProcessInfoeine bessere Überprüfung der semantischen Versionierung.

Bereitstellung unter iOS 8 und höher

Verwenden Sie für Mindestbereitstellungsziele von iOS 8.0 oder höher NSProcessInfo operatingSystemVersionoder isOperatingSystemAtLeastVersion.

Dies würde Folgendes ergeben:

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

Bereitstellung unter iOS 7

Bei einem Mindestimplementierungsziel von iOS 7.1 oder unten, benutzt vergleichen mit NSStringCompareOptions.NumericSearchauf UIDevice systemVersion.

Dies würde ergeben:

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

Lesen Sie mehr bei NSHipster .

Daniel Galasko
quelle
9

Ich behalte diese immer in meiner Constants.h-Datei:

#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
quelle
Großartig. Besser, dies in der .pchDatei Ihres XCode-Projekts
Vaibhav Jhaveri
1
Ich platziere alle meine Konstanten in meiner Constants.hDatei, die in meine pchDatei importiert wird.
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
quelle
@Jef Perioden sind keine Dezimalstellen in der Versionierung und relevant. Ihre Antwort ignoriert die Punkte nicht. Es würde fehlschlagen, wenn dies der Fall wäre. Bei der Versionierung ist jedes durch Perioden getrennte Element eine vollständige Zahl. Beispiel: '1.23.45' ist größer als '1.2.345', da das zweite Element '23' größer als '2' ist. Wenn Sie Punkte eliminieren würden, wäre dies dieselbe Zahl.
Andres Canella
6

Mit der Versionsklasse , die im Projekt nv-ios-version enthalten ist (Apache License, Version 2.0), ist es einfach, die iOS-Version abzurufen und zu vergleichen. Ein Beispielcode unten gibt die iOS-Version aus und prüft, ob die Version größer oder gleich 6.0 ist.

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

Projektseite: nv-ios-Version
TakahikoKawasaki / nv-ios-Version

Blog: Abrufen und Vergleichen der iOS-Version zur Laufzeit mit der Versionsklasse
Abrufen und Vergleichen der iOS-Version zur Laufzeit mit der Versionsklasse

Takahiko Kawasaki
quelle
5

Neue Methode zum Überprüfen der Systemversion mit der schnellen SystemVersion Forget [[UIDevice currentDevice] systemVersion] und NSFoundationVersionNumber.

Wir können NSProcessInfo -isOperatingSystemAtLeastVersion verwenden

     import Foundation

     let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
     NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
Govind
quelle
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
quelle
4

Im Allgemeinen ist es besser zu fragen, ob ein Objekt einen bestimmten Selektor ausführen kann, als eine Versionsnummer zu überprüfen, um zu entscheiden, ob sie vorhanden sein muss.

Wenn dies keine Option ist, müssen Sie hier etwas vorsichtig sein, da [@"5.0" compare:@"5" options:NSNumericSearch]Rückgaben NSOrderedDescendingmöglicherweise überhaupt nicht beabsichtigt sind. Ich könnte NSOrderedSamehier erwarten . Dies ist zumindest ein theoretisches Anliegen, gegen das es sich meiner Meinung nach zu verteidigen lohnt.

Erwägenswert ist auch die Möglichkeit einer fehlerhaften Versionseingabe, mit der nicht vernünftigerweise verglichen werden kann. Apple liefert die drei vordefinierte Konstanten definiert NSOrderedAscending, NSOrderedSameund NSOrderedDescendingdoch kann ich nach etwas , was einer Verwendung denken genannt NSOrderedUnorderedim Falle ich nicht vergleichen zwei Dinge können , und ich möchte einen Wert zurückgeben dies angibt.

Darüber hinaus ist es nicht unmöglich, dass Apple eines Tages seine drei vordefinierten Konstanten erweitert, um eine Vielzahl von Rückgabewerten zu ermöglichen, was einen Vergleich != NSOrderedAscendingunklug macht.

Betrachten Sie vor diesem Hintergrund den folgenden Code.

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
quelle
4
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

Wobei natürlich NSFoundationVersionNumber_iOS_6_1für die iOS-Version, die Sie überprüfen möchten, geändert werden muss. Was ich jetzt geschrieben habe, wird wahrscheinlich häufig verwendet, wenn getestet wird, ob auf einem Gerät iOS7 oder eine frühere Version ausgeführt wird.

OscarWyck
quelle
4

etwas spät zur Party, aber angesichts von iOS 8.0 könnte dies relevant sein:

wenn Sie vermeiden können, zu verwenden

[[UIDevice currentDevice] systemVersion]

Überprüfen Sie stattdessen, ob eine Methode / Klasse / was auch immer vorhanden ist.

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

Ich fand es nützlich für den Standortmanager, bei dem ich requestWhenInUseAuthorization für iOS 8.0 aufrufen muss, aber die Methode ist für iOS <8 nicht verfügbar

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

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

Ich weiß, dass dies eine alte Frage ist, aber jemand hätte die Makros zur Kompilierungszeit in erwähnen sollen Availability.h . Alle anderen Methoden hier sind Laufzeitlösungen und funktionieren nicht in einer Header-Datei, einer Klassenkategorie oder einer ivar-Definition.

Verwenden Sie für diese Situationen

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

h / t diese Antwort

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

Fügen Sie dann eine if-Bedingung wie folgt hinzu: -

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

Es gibt Versionen wie 7.0 oder 6.0.3, daher können wir die Version zum Vergleich einfach in Zahlen umwandeln. Wenn die Version 7.0 entspricht, fügen Sie einfach eine weitere ".0" hinzu und nehmen Sie den numerischen Wert.

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

Für 6.0.0

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

für 7.0

 if (version==700) {
   // Do something
 }
NaXir
quelle
Das einfache Entfernen der Dezimalstellen ist der falsche Ansatz. Betrachten Sie eine Komponente, die länger als 1 Zeichen ist, z 6.1.10. dann ergibt dieser Algorithmus 6110 > 700, was nicht korrekt ist.
Neu
Ich verstehe, dass Apple schlecht darin ist, neue Versionen herauszubringen, aber in den meisten Fällen ging die zweite Nummer der Version nie über 5 hinaus, sodass 10 nicht in Frage kommt. Dies ist ein Ad-hoc-Ansatz. Wenn also der Fall für zwei Komponenten behandelt wird, können Sie ihn so ändern, dass vier Fälle gleichzeitig behandelt werden, wenn Sie dies manuell tun möchten. Wie auch immer, dieser Ansatz wurde zum Zeitpunkt von iOS6 oder 7 kommentiert. IOS 9 und 10 haben viel bessere Möglichkeiten, ihn zu überprüfen, dh #verfügbar.
NaXir
2

Versuchen Sie den folgenden Code:

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

Nur zum Abrufen des Zeichenfolgenwerts der Betriebssystemversion:

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

Als Variation der Yasimturks-Lösung habe ich eine Funktion und einige Enum-Werte anstelle von fünf Makros definiert. Ich finde es eleganter, aber das ist Geschmackssache.

Verwendungszweck:

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

.h Datei:

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

BOOL systemVersion(Comparison test, NSString* version);

.m Datei:

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

Sie sollten das Präfix Ihrer App zu den Namen hinzufügen, insbesondere zum ComparisonTyp.

jcsahnwaldt sagt GoFundMonica
quelle
1

Verwenden der empfohlenen Methode ... Wenn die Header-Dateien keine Definition enthalten, können Sie die Versión jederzeit mit einem Gerät der gewünschten IOS-Versión auf der Konsole drucken lassen.

- (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
quelle
1

Lösung zum Überprüfen der iOS-Version 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")
}

Nachteil dieser Lösung: Es ist einfach eine schlechte Praxis, anhand der Versionsnummern des Betriebssystems zu prüfen, wie auch immer Sie dies tun. Man sollte Abhängigkeiten niemals auf diese Weise fest codieren, sondern immer nach Funktionen, Fähigkeiten oder der Existenz einer Klasse suchen. Bedenken Sie; Apple veröffentlicht möglicherweise eine abwärtskompatible Version einer Klasse. Wenn dies der Fall wäre, würde der von Ihnen vorgeschlagene Code diese niemals verwenden, da Ihre Logik nach einer Versionsnummer des Betriebssystems sucht und NICHT nach der Existenz der Klasse.

( Quelle dieser Informationen )

Lösung zum Überprüfen der Klassenexistenz in Swift

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

Nicht verwenden, if (NSClassFromString("UIAlertController") == nil)da es auf dem iOS-Simulator mit iOS 7.1 und 8.2 ordnungsgemäß funktioniert. Wenn Sie jedoch auf einem realen Gerät mit iOS 7.1 testen, werden Sie leider feststellen, dass Sie den anderen Teil des Code-Snippets niemals durchlaufen werden.

König-Zauberer
quelle
Warum abstimmen? Diese Lösung funktioniert perfekt mit Swift und jeder iOS-Version. Besonders die Überprüfung der Klassenexistenz ist einfach perfekt.
König-Zauberer
1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
Gank
quelle
0

Eine allgemeinere Version in Obj-C ++ 11 (Sie könnten wahrscheinlich einige dieser Dinge durch die NSString / C-Funktionen ersetzen, aber dies ist weniger ausführlich. Dies gibt Ihnen zwei Mechanismen. SplitSystemVersion bietet Ihnen ein Array aller Teile, was nützlich ist, wenn Sie möchten nur die Hauptversion einschalten (z switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }. B. ).

#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
quelle
0

Versuche dies

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { 
// do some work
}
Muhammad Aamir Ali
quelle
Erklären Sie, was dies bewirkt.
Kevin Panko
Wenn überprüft wird, ob die OS-Version iOS 7 ist oder nicht
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
quelle
float versionToBeCompared = 3.1.3;kann nicht einmal kompilieren.
Pang
0

Schnelles Beispiel, das tatsächlich funktioniert:

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

Verwenden Sie NSProcessInfo nicht, da es unter 8.0 nicht funktioniert und daher bis 2016 so gut wie unbrauchbar ist

Esqarrouth
quelle
0

Hier ist eine schnelle Version:

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

Verwendungszweck:

if iOSVersion.iOS8 {
    //Do iOS8 code here
}
Swinny89
quelle
Ich denke, Version sollte iOSVersion in Zeile 3-6 sein wiestruct 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