Jak sprawdzić wersję iOS?


848

Chcę sprawdzić, czy iOS wersja urządzenia jest lepsza niż 3.1.3 próbowałem takich rzeczy:

[[UIDevice currentDevice].systemVersion floatValue]

ale to nie działa, chcę tylko:

if (version > 3.1.3) { }

Jak mogę to osiągnąć?


5
Uwaga moderatora : Z biegiem czasu na to pytanie pojawiło się ponad 30 odpowiedzi. Przed dodaniem nowej odpowiedzi upewnij się , że Twoje rozwiązanie nie zostało jeszcze dostarczone.
Matt

3
Począwszy od Xcode 7 if #available(iOS 9, *) {}w Swift. Począwszy od Xcode 9, if (@available(iOS 11, *)) {}w celu-c.
Cœur

Odpowiedzi:


1001

Szybka odpowiedź…


Jak Swift 2.0 można używać #availablew sposób iflub guardw kodzie ochronnym, który powinien być prowadzony tylko na niektórych systemach.

if #available(iOS 9, *) {}


W Objective-C musisz sprawdzić wersję systemu i wykonać porównanie.

[[NSProcessInfo processInfo] operatingSystemVersion] w iOS 8 i nowszych.

Począwszy od Xcode 9:

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


Pełna odpowiedź…

W Objective-C i Swift w rzadkich przypadkach lepiej jest unikać polegania na wersji systemu operacyjnego jako wskazania możliwości urządzenia lub systemu operacyjnego. Zwykle istnieje bardziej niezawodna metoda sprawdzania, czy dostępna jest określona funkcja lub klasa.

Sprawdzanie obecności interfejsów API:

Na przykład możesz sprawdzić, czy UIPopoverControllerjest dostępny na bieżącym urządzeniu, używając NSClassFromString:

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

W przypadku słabo połączonych klas wysyłanie wiadomości do klasy jest bezpieczne. W szczególności działa to w ramach, które nie są jawnie powiązane jako „Wymagane”. W przypadku brakujących klas wyrażenie przyjmuje wartość zero, co nie spełnia warunku:

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

Niektóre klasy, takie jak CLLocationManageri UIDevice, zapewniają metody sprawdzania możliwości urządzenia:

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

Sprawdzanie obecności symboli:

Bardzo rzadko musisz sprawdzić obecność stałej. Pojawiło się to w iOS 8 wraz z wprowadzeniem UIApplicationOpenSettingsURLString, używanej do ładowania aplikacji Ustawienia przez -openURL:. Wartość nie istniała przed iOS 8. Przekazywanie wartości zerowej do tego interfejsu API ulegnie awarii, dlatego najpierw należy sprawdzić, czy istnieje stała:

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

Porównanie z wersją systemu operacyjnego:

Załóżmy, że masz do czynienia ze stosunkowo rzadką potrzebą sprawdzenia wersji systemu operacyjnego. W przypadku projektów kierowanych na iOS 8 i NSProcessInfonowsze wersje zawiera metodę przeprowadzania porównań wersji z mniejszą szansą na błąd:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Projekty ukierunkowane na starsze systemy mogą korzystać systemVersionz UIDevice. Apple używa go w przykładowym kodzie 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;
}

Jeśli z jakiegokolwiek powodu zdecydujesz, że systemVersiontego właśnie chcesz, potraktuj go jak ciąg znaków lub ryzykujesz obcięciem numeru wersji łatki (np. 3.1.2 -> 3.1).


161
Istnieją szczególne przypadki, w których sprawdzanie wersji systemu jest uzasadnione. Na przykład kilka klas i metod, które były prywatne w wersji 3.x, zostały upublicznione w wersji 4.0, więc jeśli po prostu sprawdzisz ich dostępność, uzyskasz zły wynik w wersji 3.x. Ponadto sposób, w jaki UIScrollViews obsługuje skale zoomu, zmienił się subtelnie w wersji 3.2 i nowszych, dlatego trzeba będzie sprawdzić wersje systemu operacyjnego, aby odpowiednio przetworzyć wyniki.
Brad Larson

2
iOS 3.2 nie wydaje się wysyłać -viewWillAppearw UISplitViewController. Mój hack polega na ustaleniu, czy <iOS 4.0 i przesłanie go samemu do kontrolera widoku szczegółowego w widoku głównym -didSelectRowAtIndexPath.
jww

10
Musisz być tutaj nieco ostrożny, ponieważ [@"10.0" compare:@"10" options:NSNumericSearch]zwroty NSOrderedDescending, które mogą wcale nie być zamierzone. (Mogę się spodziewać NSOrderedSame.) To jest przynajmniej teoretyczna możliwość.
SK9,

Tak, właśnie spotkałem przypadek, w którym trzeba było obejść błąd iOS 5. respondsToSelectori inni nie wykonaliby pracy - musieli porównywać wersje.
Hot Licks,

2
Wraz z wprowadzeniem TVos stało się to jeszcze ważniejsze. Zobacz, jak TVos zwróci 9.0, gdy używany jest zestaw SDK 9.1. Więc sprawdź klasę lub metodę (selektor) jest najlepszym sposobem, po tym powinieneś sprawdzić NSFoundationVersionNumberi tylko jeśli nie jest to możliwe, powinieneś sprawdzić wersje systemu 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. Trzymanie tego w nagłówku, który możesz dołączyć w razie potrzeby, jest najłatwiejszym rozwiązaniem, jakie mogę wymyślić. W kilku przypadkach jest to bardziej niezawodne niż sprawdzanie dostępności za pomocą NSClassFromString. Innym przykładem jest iAd, gdzie jeśli używasz ADBannerContentSizeIdentifierPortrait w wersji wcześniejszej niż 4.2, dostaniesz EXEC_BAD_ACCESS, ale równoważna ADBannerContentSizeIdentifier320x50 jest przestarzała po 4.1.
Rab

1
Innym miejscem, z którego korzystam, jest UIPageViewController i ustawienie stylu na UIPageViewControllerTransitionStyleScroll w iOS6.
Paul de Lange

7
To nie działa przez 10 sekund. Na przykład porównanie 4.10 i 4.9 dałoby zły wynik.
pzulw

7
Należy zachować ostrożność podczas korzystania z .0numerów opcjonalnych . Na przykład SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")daje niepoprawny wynik w systemie iOS 7.0.
Yan

1
Właśnie przetestowałem umieszczenie tego w moim pliku .pch i działa świetnie (budowanie z Xcode 5 przynajmniej)
Whyoz

253

Jak sugerują oficjalne dokumenty Apple : możesz użyć NSFoundationVersionNumber, z NSObjCRuntime.hpliku nagłówka.

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

40
+1 To w rzeczywistości najbezpieczniejsza i najdokładniejsza opcja tutaj.
mxcl

8
Um .. NSFoundationVersionNumber_iOS_6_1nie istnieje w iOS 5 SDK.
lipca 13 lipca

2
@ Julie możesz samodzielnie zdefiniować brakujące numery wersji: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (spójrz na linię 102-130)
CarlJ

3
nie, mylisz się, NSFoundationVersionNumber_iOS_7_0 nie istnieje. Ale cóż, możemy to zdefiniować za pomocą #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Aby uniknąć takich bałaganów, wybrałem makro SYSTEM_VERSION_LESS_THAN (v) z yasirmturk
Cœur

7
Nie, ale Apple doda NSFoundationVersionNumber_iOS_8_0iOS 9. Po prostu sprawdź NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ

111

Począwszy od Xcode 9 w celu C :

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

Począwszy od Xcode 7 w Swift :

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

W przypadku wersji można określić MAJOR, MINOR lub PATCH ( definicje na stronie http://semver.org/ ). Przykłady:

  • iOS 11i iOS 11.0są w tej samej minimalnej wersji
  • iOS 10, iOS 10.3 , iOS 10.3.1Są różne wersje minimalne

Możesz wprowadzić wartości dla dowolnego z tych systemów:

  • iOS, macOS,watchOS ,tvOS

Prawdziwy przykład z jednej z moich kapsułek :

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

dokumentacja


Jak można to odwrócić w Objective-C lub Swift?
Bezdzietny

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

Czy mogę używać guardw celu C zamiast pozostawiać blok otwarty i wcięcie w elseinstrukcji?
Bezdzietny

@Legoless nie, po prostu użyj pustego ifbloku, a następnie znaku else.
Cœur

1
To rozwiązanie, które obecnie mam, po prostu chciałem uniknąć niepotrzebnych wcięć i pustych ifbloków.
Bezdzietny

45

Służy to do sprawdzania kompatybilności wersji SDK w Xcode, to jest, jeśli masz duży zespół z różnymi wersjami Xcode lub wieloma projektami obsługującymi różne SDK, które współużytkują ten sam kod:

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

Naprawdę chcesz sprawdzić wersję iOS na urządzeniu. Możesz to zrobić w ten sposób:

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

Wersja szybka:

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
}

Obecne wersje swift powinny używać tego:

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

37

Próbować:

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
Dlaczego nie odwrócić kolejności tutaj i zapisać porównanie, ponieważ zarówno @ „3.1.3”, jak i systemVersion są NSStrings? Tj .: `if ([@" 3.1.3 "porównaj: [UIDevice currentDevice] .systemVersion opcje: NSNumericSearch] == NSOrdersDescending); // wersja OS> = 3.1.3 else; // wersja OS <3.1.3`
Rob

3
Może to uczynić logikę mniej przejrzystą. Operacja powinna być jednak równoważna.
Jonathan Grynspan

1
Porównanie dwóch liczb całkowitych z pewnością nie jest bardzo drogie.
KPM

To naprawdę kwestia stylu. Koszt wysyłki wiadomości znacznie przewyższy dodatkowe porównanie liczb całkowitych.
Jonathan Grynspan

35

Preferowane podejście

W Swift 2.0 Apple dodał sprawdzanie dostępności przy użyciu znacznie wygodniejszej składni (czytaj więcej tutaj ). Teraz możesz sprawdzić wersję systemu operacyjnego, stosując czystszą składnię:

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

Jest to preferowane zamiast sprawdzania respondsToSelectoritp. ( Co nowego w Swift ). Teraz kompilator zawsze ostrzega, jeśli nie strzeżesz poprawnie swojego kodu.


Pre Swift 2.0

Nowością w iOS 8 jest NSProcessInfomożliwość lepszej kontroli semantycznej wersji.

Wdrażanie w systemie iOS 8 i nowszych

Aby uzyskać minimalne cele wdrażania systemu iOS 8.0 lub nowszego, użyj NSProcessInfo operatingSystemVersionlub isOperatingSystemAtLeastVersion.

Dałoby to:

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

Wdrażanie na iOS 7

Aby uzyskać minimalne cele wdrażania dla systemu iOS 7.1 lub niższego, użyj opcji porównania z NSStringCompareOptions.NumericSearchna UIDevice systemVersion.

Dałoby to:

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

Więcej lektur na NSHipster .


9

Zawsze przechowuję je w moim pliku 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)

Świetny. Lepiej umieścić to w .pchpliku swojego projektu XCode
Vaibhav Jhaveri

1
Wszystkie moje stałe umieszczam w Constants.hpliku zaimportowanym do mojego pchpliku.
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 Okresy nie są miejscami dziesiętnymi w wersji i są istotne. Twoja odpowiedź nie ignoruje kropek. Gdyby tak się stało, poniósłby porażkę. W wersjonowaniu każdy okres oddzielany element jest liczbą całkowitą. Np .: „1.23.45” jest większy niż „1.2.345”, ponieważ drugi element „23” jest większy niż „2”. Jeśli wyeliminujesz kropki, będzie to ta sama liczba.
Andres Canella,

6

Dzięki klasie Version zawartej w projekcie nv-ios-version (Licencja Apache, wersja 2.0) można łatwo uzyskać i porównać wersję iOS. Przykładowy kod poniżej zrzuca wersję iOS i sprawdza, czy wersja jest większa lub równa 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.
}

Strona projektu: wersja nv-ios TakahikoKawasaki / wersja
nv-ios

Blog: Pobierz i porównaj wersję iOS w czasie wykonywania z klasą Version
Pobierz i porównaj wersję iOS w czasie wykonywania z klasą Version


5

Nowy sposób sprawdzenia wersji systemu za pomocą szybkiego Forget [[UIDevice currentDevice] systemVersion] i NSFoundationVersionNumber.

Możemy użyć 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

Ogólnie lepiej jest zapytać, czy obiekt może wykonać dany selektor, niż sprawdzać numer wersji, aby zdecydować, czy musi on być obecny.

Jeśli nie jest to opcja, musisz być nieco ostrożny, ponieważ [@"5.0" compare:@"5" options:NSNumericSearch]zwroty, NSOrderedDescendingktóre mogą nie być wcale zamierzone; Mogę się NSOrderedSametu spodziewać . Jest to przynajmniej kwestia teoretyczna, przed którą moim zdaniem warto się bronić.

Warto również wziąć pod uwagę możliwość wprowadzenia złej wersji, której nie można racjonalnie porównać. Jabłko dostarcza trzy predefiniowane stałe NSOrderedAscending, NSOrderedSamea NSOrderedDescendingjednak mogę myśleć o użyciu dla niektórych rzeczy zwanejNSOrderedUnordered w przypadku nie mogę porównać dwie rzeczy i chcę zwrócić wartość wskazującą ten.

Co więcej, nie jest niemożliwe, że Apple pewnego dnia rozszerzy swoje trzy predefiniowane stałe, aby umożliwić różne wartości zwracane, co czyni porównanie != NSOrderedAscendingnierozsądnym.

Powiedziawszy to, rozważ następujący kod.

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
}

Gdzie oczywiście NSFoundationVersionNumber_iOS_6_1należy zmienić na odpowiednie dla wersji iOS, którą chcesz sprawdzić. To, co teraz napisałem, prawdopodobnie będzie często używane podczas testowania, czy urządzenie ma system iOS7 lub poprzednią wersję.


4

nieco późno na imprezę, ale w świetle iOS 8.0 może to mieć znaczenie:

jeśli możesz uniknąć używania

[[UIDevice currentDevice] systemVersion]

Zamiast tego sprawdź, czy istnieje metoda / klasa / cokolwiek innego.

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

Okazało się, że jest to przydatne dla menedżera lokalizacji, w którym muszę wywołać requestWhenInUseAuthorization dla iOS 8.0, ale metoda nie jest dostępna dla iOS <8


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

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

3

Wiem, że to stare pytanie, ale ktoś powinien wspomnieć o makrach czasu kompilacji Availability.h. Wszystkie inne metody tutaj są rozwiązaniami uruchomieniowymi i nie będą działać w pliku nagłówkowym, kategorii klasy lub definicji ivar.

W takich sytuacjach użyj

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

h / t tej odpowiedzi


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

Następnie dodaj warunek if w następujący sposób:

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

2

Istnieją wersje takie jak 7.0 lub 6.0.3, więc możemy po prostu przekonwertować wersję na numeryczną w celu porównania. jeśli wersja jest jak 7.0, po prostu dodaj do niej kolejny „.0”, a następnie pobierz jego wartość liczbową.

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

Dla 6.0.0

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

dla 7.0

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

po prostu usunięcie kropki dziesiętnej jest niewłaściwym podejściem. rozważ komponent, który ma więcej niż 1 znak, np 6.1.10. wtedy algorytm da wynik 6110 > 700, co nie jest poprawne.
nowy

Rozumiem, że Apple źle radzi sobie z wprowadzaniem nowych wersji, ale przez większość czasu druga liczba nigdy nie przekraczała 5, więc 10 nie wchodzi w rachubę. Jest to podejście doraźne, więc jeśli obsługuje wielkość liter dla 2 składników, możesz ją zmodyfikować tak, aby obsługiwała wielkość liter w czterech literach, jeśli chcesz to zrobić ręcznie. W każdym razie to podejście zostało skomentowane w iOS6 lub 7. iOS 9 i 10 mają znacznie lepsze sposoby sprawdzania go, tj. # Dostępne.
NaXir

2

Wypróbuj poniższy kod:

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


1

Jako wariant rozwiązania yasimturks zdefiniowałem jedną funkcję i kilka wartości wyliczeniowych zamiast pięciu makr. Uważam, że jest bardziej elegancki, ale to kwestia gustu.

Stosowanie:

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

plik .h:

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

BOOL systemVersion(Comparison test, NSString* version);

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

Powinieneś dodać prefiks aplikacji do nazw, szczególnie do Comparisontypu.


1

Korzystając z zalecanego zalecanego sposobu ... jeśli nie ma definicji w plikach nagłówków, zawsze możesz uzyskać wersję drukującą ją na konsoli z urządzeniem o pożądanej wersji IOS.

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

Rozwiązanie do sprawdzania wersji iOS w 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")
}

Wada tego rozwiązania: sprawdzanie przy użyciu numerów wersji systemu operacyjnego jest po prostu złą praktyką. Nigdy nie należy w ten sposób ustalać zależności kodu, zawsze sprawdzać cechy, możliwości lub istnienie klasy. Rozważ to; Apple może wydać kompatybilną z poprzednią wersją klasę, jeśli tak, to sugerowany kod nigdy go nie użyje, ponieważ logika szuka numeru wersji systemu operacyjnego, a NIE istnienia klasy.

( Źródło tej informacji )

Rozwiązanie do sprawdzania istnienia klasy w Swift

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

Nie używaj, if (NSClassFromString("UIAlertController") == nil)ponieważ działa poprawnie na symulatorze iOS z iOS 7.1 i 8.2, ale jeśli testujesz na prawdziwym urządzeniu z iOS 7.1, niestety zauważysz, że nigdy nie przejdziesz przez pozostałą część fragmentu kodu.


Dlaczego głosować w dół? To rozwiązanie działa idealnie przy użyciu Swift i dowolnej wersji iOS. Zwłaszcza sprawdzenie istnienia klasy jest po prostu idealne.
King-Wizard

1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)

0

Bardziej ogólna wersja w Obj-C ++ 11 (prawdopodobnie możesz zastąpić niektóre z tych rzeczy funkcjami NSString / C, ale jest to mniej szczegółowe. To daje dwa mechanizmy. SplitSystemVersion daje tablicę wszystkich części, co jest przydatne, jeśli po prostu chcesz włączyć wersję główną (np 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;nie można nawet skompilować.
Pang

0

Szybki przykład, który faktycznie działa:

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

Nie używaj NSProcessInfo, ponieważ nie działa pod wersją 8.0, więc jest prawie bezużyteczne do 2016 roku


0

Oto szybka wersja:

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

Stosowanie:

if iOSVersion.iOS8 {
    //Do iOS8 code here
}

Myślę, że wersja powinna być iOSVersion w linii 3-6 jak 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.