Como verificar a versão do iOS?

848

Quero verificar se a iOSversão do dispositivo é maior do 3.1.3 que tentei coisas como:

[[UIDevice currentDevice].systemVersion floatValue]

mas não funciona, eu só quero um:

if (version > 3.1.3) { }

Como posso conseguir isso?

John
fonte
5
Nota do moderador : Com o tempo, esta pergunta acumulou mais de 30 respostas. Antes de adicionar uma nova resposta, verifique se sua solução ainda não foi fornecida.
Matt
3
Iniciando o Xcode 7, if #available(iOS 9, *) {}no Swift. Iniciando o Xcode 9, if (@available(iOS 11, *)) {}no objetivo-c.
Cœur

Respostas:

1002

A resposta rápida ...


A partir do Swift 2.0, você pode usar #availableum ifou guardpara proteger código que só deve ser executado em determinados sistemas.

if #available(iOS 9, *) {}


No Objective-C, você precisa verificar a versão do sistema e realizar uma comparação.

[[NSProcessInfo processInfo] operatingSystemVersion] no iOS 8 e superior.

A partir do Xcode 9:

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


A resposta completa…

Em Objective-C e Swift, em casos raros, é melhor evitar confiar na versão do sistema operacional como uma indicação dos recursos do dispositivo ou do sistema operacional. Geralmente, existe um método mais confiável para verificar se um recurso ou classe específico está disponível.

Verificando a presença de APIs:

Por exemplo, você pode verificar se UIPopoverControllerestá disponível no dispositivo atual usando NSClassFromString:

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

Para classes fracamente vinculadas, é seguro enviar uma mensagem diretamente para a classe. Notavelmente, isso funciona para estruturas que não estão explicitamente vinculadas como "Necessárias". Para classes ausentes, a expressão é avaliada como nula, com falha na condição:

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

Algumas classes, como CLLocationManagere UIDevice, fornecem métodos para verificar os recursos do dispositivo:

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

Verificando a presença de símbolos:

Muito ocasionalmente, você deve verificar a presença de uma constante. Isso surgiu no iOS 8 com a introdução de UIApplicationOpenSettingsURLString, usado para carregar o aplicativo Configurações via -openURL:. O valor não existia antes do iOS 8. A falta de nada para esta API trava, portanto, verifique primeiro a existência da constante:

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

Comparando com a versão do sistema operacional:

Vamos supor que você se depare com a necessidade relativamente rara de verificar a versão do sistema operacional. Para projetos direcionados ao iOS 8 e superior, NSProcessInfoinclui um método para realizar comparações de versão com menos chance de erro:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Projetos voltados para sistemas mais antigos podem usar systemVersionno UIDevice. A Apple o usa em seu código de amostra 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, por qualquer motivo, você decidir que systemVersioné isso o que deseja, trate-o como uma sequência ou corre o risco de truncar o número de revisão do patch (por exemplo, 3.1.2 -> 3.1).

Justin
fonte
161
Existem casos específicos em que a verificação da versão do sistema é garantida. Por exemplo, algumas classes e métodos que eram privados n 3.x foram tornados públicos no 4.0, portanto, se você simplesmente verificasse a disponibilidade deles, obteria um resultado errado no 3.x. Além disso, a maneira como o UIScrollViews lida com as escalas de zoom mudou sutilmente no 3.2 e acima; portanto, você precisa verificar as versões do sistema operacional para processar os resultados adequadamente.
Brad Larson
2
O iOS 3.2 não parece enviar -viewWillAppeara UISplitViewController. Meu truque é determinar se o <iOS 4.0 e enviá-lo para o Controlador de exibição de detalhes nas exibições raiz -didSelectRowAtIndexPath.
JWW
10
Você precisa ter um pouco de cuidado aqui, porque [@"10.0" compare:@"10" options:NSNumericSearch]retornos NSOrderedDescending, que podem muito bem não ser planejados. (Eu poderia esperar NSOrderedSame.) Essa é pelo menos uma possibilidade teórica.
SK9
Sim, acabei de encontrar um caso em que um bug do iOS 5 precisava ser contornado. respondsToSelectoret al não fariam o trabalho - tem que comparar versões.
Hot Licks
2
Com a introdução dos TVos, isso se tornou ainda mais importante. Veja como os TVos retornarão 9.0 enquanto o SDK 9.1 é usado. Portanto, verifique se a classe ou o método (seletor) é o melhor caminho; depois disso, você deve verificar NSFoundationVersionNumberoe somente se isso não for possível, deve verificar as versões do sistema UIDevice.
Rckoenes #
1055
/*
 *  System Versioning Preprocessor Macros
 */ 

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

/*
 *  Usage
 */ 

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

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
    ...
}
yasirmturk
fonte
20
+1. Manter isso em um cabeçalho que você possa incluir onde for necessário é a solução mais fácil que consigo pensar. Em vários casos, isso é mais confiável do que verificar a disponibilidade usando o NSClassFromString. Outro exemplo está no iAd, onde se você usar ADBannerContentSizeIdentifierPortrait em uma versão anterior à 4.2, obterá EXEC_BAD_ACCESS, mas o ADBannerContentSizeIdentifier320x50 equivalente será descontinuado após 4.1.
Rab
1
Outro lugar que eu uso é com o UIPageViewController e definindo o estilo como UIPageViewControllerTransitionStyleScroll no iOS6.
Paul de Lange
7
Isso não funciona para 10s. Por exemplo, comparar 4.10 e 4.9 daria o resultado errado.
pzulw
7
Deve-se ter muito cuidado ao usar .0números opcionais . Por exemplo, SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")fornece resultado incorreto no iOS 7.0.
Yan
1
Eu apenas testada colocando isso no meu arquivo .pch e ele funciona muito bem (edifício com Xcode 5 pelo menos)
whyoz
253

Conforme sugerido pelos documentos oficiais da Apple : você pode usar o NSFoundationVersionNumber, no NSObjCRuntime.harquivo de cabeçalho.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}
CarlJ
fonte
40
+1 Esta é de fato a opção mais segura e precisa aqui.
Mxcl 11/09/13
8
Um .. NSFoundationVersionNumber_iOS_6_1não existe no iOS 5 SDK.
Kjuly
2
@Kjuly você pode definir os números de versão ausentes por si mesmo: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (dê uma olhada na linha 102-130)
CarlJ
3
não, você está errado, NSFoundationVersionNumber_iOS_7_0 não existe. Mas bem, nós poderíamos defini-lo com #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Para evitar mexer dessa maneira, eu fui com a macro SYSTEM_VERSION_LESS_THAN (v) de yasirmturk
Cœur
7
Não, mas a Apple irá adicionar o NSFoundationVersionNumber_iOS_8_0no iOS 9. apenas verificar se há NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ
111

Iniciando o Xcode 9, no Objective-C :

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

Iniciando o Xcode 7, no Swift :

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

Para a versão, você pode especificar o MAJOR, o MINOR ou o PATCH (consulte http://semver.org/ para obter definições). Exemplos:

  • iOS 11e iOS 11.0são a mesma versão mínima
  • iOS 10, iOS 10.3, iOS 10.3.1São diferentes versões mínimas

Você pode inserir valores para qualquer um desses sistemas:

  • iOS, macOS, watchOS,tvOS

Exemplo de caso real retirado de um dos meus pods :

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

documentação

Cœur
fonte
Como isso pode ser invertido no Objective-C ou no Swift?
Legoless
@Legolessif (...) {} else { ... }
Coeur
Posso usar guardno Objective-C em vez de deixar o bloco aberto e recuar na elseinstrução?
Legoless 19/09
@ Não legível, basta usar um ifbloco vazio seguido por um else.
19417 Cœur
1
Essa é a solução que tenho atualmente, só queria evitar recuos desnecessários e ifblocos vazios .
Legoless 19/09
45

Isso é usado para verificar a versão do SDK compatível no Xcode, isto é, se você tiver uma equipe grande com versões diferentes do Xcode ou vários projetos que suportam SDKs diferentes que compartilham o mesmo código:

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

O que você realmente deseja é verificar a versão do iOS no dispositivo. Você pode fazer isso com isso:

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

Versão Swift:

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
}

As versões atuais do swift devem usar isso:

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

Tentar:

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
fonte
2
Por que não reverter a ordem aqui e salvar uma comparação, já que @ @ 3.1.3 "e systemVersion são NSStrings? Ou seja: `if ([@" 3.1.3 "compare: [UIDevice currentDevice] .systemVersion options: NSNumericSearch] == NSOrderedDescending); // Versão do SO> = 3.1.3 else; // Versão do SO <3.1.3`
Rob
3
Isso pode tornar a lógica menos clara. A operação deve ser equivalente, no entanto.
Jonathan Grynspan
1
Uma comparação entre dois números inteiros certamente não é muito cara.
KPMG
É realmente uma questão de estilo. A sobrecarga do envio de mensagens superará largamente a comparação de números inteiros extras.
22612 Jonathan Grynspan
35

Abordagem preferida

No Swift 2.0, a Apple adicionou a verificação de disponibilidade usando uma sintaxe muito mais conveniente (Leia mais aqui ). Agora você pode verificar a versão do sistema operacional com uma sintaxe mais limpa:

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

Este é o preferido sobre a verificação respondsToSelectoretc ( O que há de novo no Swift ). Agora, o compilador sempre avisará se você não estiver protegendo seu código corretamente.


Pre Swift 2.0

O novo no iOS 8 está NSProcessInfopermitindo melhores verificações de versão semântica.

Implementando no iOS 8 e superior

Para destinos mínimos de implantação do iOS 8.0 ou superior, use NSProcessInfo operatingSystemVersionou isOperatingSystemAtLeastVersion.

Isso produziria o seguinte:

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

Implantando no iOS 7

Para destinos mínimos de implantação do iOS 7.1 ou inferior, use compare com NSStringCompareOptions.NumericSearchon UIDevice systemVersion.

Isso renderia:

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

Mais leitura em NSHipster .

Daniel Galasko
fonte
9

Eu sempre mantenho aqueles no meu arquivo Constants.h:

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES) 
#define IS_OS_5_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)
#define IS_OS_6_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
#define IS_OS_8_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
Segev
fonte
Ótimo. Melhor colocar isso no .pcharquivo de seu projeto Xcode
Vaibhav Jhaveri
1
Coloco todas as minhas constantes no meu Constants.harquivo que são importadas no meu pcharquivo.
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
fonte
Os períodos @Jef não são pontos decimais no controle de versão e são relevantes. Sua resposta não ignora os períodos; falharia se o fizesse. No controle de versão, cada elemento separado por período é um número completo. Ex: '1.23.45' é maior que '1.2.345', pois o segundo elemento '23' é maior que '2'. Se você eliminasse períodos, seria o mesmo número.
Andres Canella
6

Com a classe Version contida no projeto nv-ios-version (Licença Apache, versão 2.0), é fácil obter e comparar a versão do iOS. Um código de exemplo abaixo despeja a versão do iOS e verifica se a versão é maior ou igual a 6.0.

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

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

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

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

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

Página do projeto: nv-ios-version
TakahikoKawasaki / nv-ios-version

Blog: Obtenha e compare a versão do iOS em tempo de
execução com a classe Version

Takahiko Kawasaki
fonte
5

Nova maneira de verificar a versão do sistema usando o rápido Forget [[UIDevice currentDevice] systemVersion] e NSFoundationVersionNumber.

Podemos usar NSProcessInfo -isOperatingSystemAtLeastVersion

     import Foundation

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

Em geral, é melhor perguntar se um objeto pode executar um determinado seletor, em vez de verificar um número de versão para decidir se ele deve estar presente.

Quando isso não é uma opção, você precisa ter um pouco de cuidado aqui, porque [@"5.0" compare:@"5" options:NSNumericSearch]retornos NSOrderedDescendingque podem muito bem não ser pretendidos; Eu poderia esperar NSOrderedSameaqui. Essa é pelo menos uma preocupação teórica, que vale a pena defender contra, na minha opinião.

Também vale a pena considerar é a possibilidade de uma entrada de versão ruim, que não pode ser razoavelmente comparada. A Apple fornece as três constantes predefinidas NSOrderedAscending, NSOrderedSamee NSOrderedDescendingmas eu posso pensar de um uso para alguma coisa chamada NSOrderedUnorderedem caso eu não posso comparar duas coisas e eu quero retornar um valor indicando isso.

Além disso, não é impossível que a Apple um dia expanda suas três constantes predefinidas para permitir uma variedade de valores de retorno, fazendo uma comparação != NSOrderedAscendingimprudente.

Com isso dito, considere o seguinte código.

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

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

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

Onde é claro, NSFoundationVersionNumber_iOS_6_1deve ser alterado para aplicável à versão do iOS que você deseja verificar. O que eu escrevi agora provavelmente será muito usado ao testar se um dispositivo está executando o iOS7 ou uma versão anterior.

OscarWyck
fonte
4

um pouco atrasado para a festa, mas à luz do iOS 8.0 lá fora, isso pode ser relevante:

se você pode evitar o uso

[[UIDevice currentDevice] systemVersion]

Em vez disso, verifique a existência de um método / classe / qualquer outra coisa.

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

Achei que era útil para o gerenciador de localizações, em que preciso chamar requestWhenInUseAuthorization for iOS 8.0, mas o método não está disponível para iOS <8

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

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

Sei que essa é uma pergunta antiga, mas alguém deveria ter mencionado as macros em tempo de compilação Availability.h. Todos os outros métodos aqui são soluções de tempo de execução e não funcionarão em um arquivo de cabeçalho, categoria de classe ou definição de ivar.

Para essas situações, use

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

h / t esta resposta

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

Em seguida, adicione uma condição if da seguinte maneira: -

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

Existem versões como 7.0 ou 6.0.3, para que possamos simplesmente converter a versão em números para comparar. se a versão for como 7.0, basta acrescentar outro ".0" a ela e, em seguida, levar seu valor numérico.

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

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

For 6.0.0

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

para 7.0

 if (version==700) {
   // Do something
 }
NaXir
fonte
simplesmente remover os pontos decimais é a abordagem errada. considere um componente com mais de 1 caractere, por exemplo 6.1.10. então esse algoritmo produzirá 6110 > 700, o que não está correto.
ardnew
Eu entendo que a apple é ruim em lançar novas versões, mas na maioria das vezes o segundo número da versão nunca foi além de 5, então 10 está fora de questão. Essa é uma abordagem ad-hoc; portanto, se ele manipular maiúsculas e minúsculas para 2 componentes, você poderá modificá-lo para lidar com quatro maiúsculas e minúsculas se quiser fazer manualmente. De qualquer forma, essa abordagem foi comentada no iOS6 ou 7. O iOS 9 e 10 têm maneiras muito melhores de verificá-la, ou seja, #available.
NaXir
2

Experimente o código abaixo:

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

Apenas para recuperar o valor da string da versão do SO:

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

Como uma variação da solução yasimturks, defini uma função e alguns valores de enumeração em vez de cinco macros. Acho mais elegante, mas isso é uma questão de gosto.

Uso:

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

arquivo .h:

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

BOOL systemVersion(Comparison test, NSString* version);

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

Você deve adicionar o prefixo do seu aplicativo aos nomes, especialmente ao Comparisontipo.

jcsahnwaldt disse GoFundMonica
fonte
1

Usando a maneira recomendada mencionada ... se não houver definição nos arquivos de cabeçalho, você poderá obter a versão imprimindo-a no console com um dispositivo da versão IOS desejada.

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

Solução para verificar a versão iOS no 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")
}

Con desta solução: é simplesmente uma má prática verificar os números de versão do sistema operacional, da maneira que você faz. Nunca se deve codificar as dependências dessa maneira, sempre verifique se há recursos, capacidades ou a existência de uma classe. Considere isto; A Apple pode lançar uma versão compatível com versões anteriores de uma classe, se o fizesse, o código sugerido nunca a usaria, pois sua lógica procura um número de versão do sistema operacional e NÃO a existência da classe.

( Fonte desta informação )

Solução para verificar a existência de classe no Swift

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

Não use if (NSClassFromString("UIAlertController") == nil)porque ele funciona corretamente no simulador do iOS usando o iOS 7.1 e 8.2, mas se você testar em um dispositivo real usando o iOS 7.1, infelizmente perceberá que nunca passará pela outra parte do snippet de código.

O rei da bruxaria
fonte
Por que votar? Esta solução funciona perfeitamente usando o Swift e qualquer versão do iOS. Especialmente a verificação da existência de classe é simplesmente perfeita.
King-Wizard
1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
Gank
fonte
0

Uma versão mais genérica no Obj-C ++ 11 (você provavelmente poderia substituir algumas dessas coisas pelas funções NSString / C, mas isso é menos detalhado. Isso oferece dois mecanismos. SplitSystemVersion fornece uma matriz de todas as partes úteis se você só deseja ativar a versão principal (por exemplo 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;
}
Vitali
fonte
0

Tente isto

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { 
// do some work
}
Muhammad Aamir Ali
fonte
Explique o que isso faz.
21414 Kevin Kanko
se irá verificar se a versão do sistema operacional é iOS 7 ou não
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
fonte
float versionToBeCompared = 3.1.3;não pode nem compilar.
Pang
0

Exemplo rápido que realmente funciona:

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

Não use o NSProcessInfo porque ele não funciona com o 8.0, por isso é praticamente inútil até 2016

Esqarrouth
fonte
0

Aqui está uma versão rápida:

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

Uso:

if iOSVersion.iOS8 {
    //Do iOS8 code here
}
Swinny89
fonte
Eu acho que a versão deve ser iOSVersion na linha 3-6 comostruct 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