¿Cuáles son los casos de uso común para __IPHONE_OS_VERSION_MAX_ALLOWED?

¿Cuáles son las situaciones en las que usaría la verificación __IPHONE_OS_VERSION_MAX_ALLOWED? ¿Qué pasa con __IPHONE_OS_VERSION_MIN_REQUIRED?

Es importante comprender que se trata de constantes de time de compilation , por lo tanto, no son útiles para detectar en time de ejecución qué plataforma o versión del sistema operativo se está ejecutando (por ejemplo, detectar si se está ejecutando en iPad vs iPhone).

Lo que hacen estas constantes es permitirle detectar en el momento de compilation si el código se está construyendo para un SDK dado o para un objective de implementación. Por ejemplo, si escribió una biblioteca de código abierto que contiene código que solo funciona cuando se comstack contra el SDK de iOS 5, puede include esta comprobación para detectar en qué SDK se comstack el código:

 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 50000 //you can use iOS 5 APIs here because the SDK supports them //but the code may still crash if run on an iOS 4 device #else //this code can't use iOS 5 APIs as the SDK version doesn't support them #endif 

O, como alternativa, si desea ver cuál es la versión mínima del sistema operativo que se está orientando es …

 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000 //minimum deployment target is 5.0, so it's safe to use iOS 5-only code #else //you can use iOS5 APIs, but the code will need to be backwards //compatible or it will crash when run on an iOS 4 device #endif 

Esto es diferente de detectar en el time de ejecución qué sistema operativo está ejecutando. Si comstack el código en el primer ejemplo anterior utilizando el SDK de iOS 4, usará su código de iOS 4 seguro, pero no aprovechará ninguna característica de iOS 5 cuando se ejecute en un dispositivo iOS 5. Si lo crea utilizando el SDK de iOS 5, establezca el objective de implementación en iOS 4 e intente ejecutarlo en un dispositivo iOS 4, se comstackrá e instalará bien, pero aún puede fallar en time de ejecución porque las API de iOS 5 no existen.

En el segundo ejemplo anterior, si establece su objective de implementación en iOS 4 o inferior, utilizará la ruta de código seguro para iOS 4, pero si configura el objective de implementación en iOS 5, no se ejecutará en absoluto en un iOS 4 dispositivo (se negará a instalar).

Para crear una aplicación que se ejecute en iOS 4 y 5 y aún pueda aprovechar las características de iOS 5 si están disponibles, debe realizar una detección de time de ejecución . Para detectar la versión de iOS en time de ejecución, puede hacer esto:

 if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0.1" options:NSNumericSearch] != NSOrdenetworkingAscending) { //running on iOS 5.0.1 or higher } 

Pero eso significa mantener un logging de exactamente qué características de API se agregaron en qué versión del sistema operativo, que es torpe y solo se debe hacer como último recurso. Por lo general, un mejor enfoque es utilizar la detección de características, así:

 if ([SomeClass class]) { //this class exists } if ([SomeClass instancesRespondToSelector:@selector(someMethod:)]) { //this method exists } 

Además, para detectar en time de ejecución si estás en un iPad o iPhone, puedes hacer esto:

 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { //on an ipad } 

Realizar estas comprobaciones en time de ejecución le permite crear una sola aplicación que se ejecute en múltiples dispositivos y versiones de iOS y que sea capaz de aprovechar las características de cada plataforma.

una implementación práctica / ejemplo de uso de instancesRespondToSelector:, expandiéndose en @Nick Lockwood's anwser:

 +(BOOL) testIsHeaderInConnectData:(NSData *) connectData { static NSString *headString = nil; static NSData *headData = nil; static BOOL rangeCheckOk = NO; static BOOL rangeCheckTestComplete = NO; if (!rangeCheckTestComplete) { rangeCheckOk = [NSData instancesRespondToSelector:@selector(rangeOfData:options:range:)]; headString = @"HEAD "; headData = (rangeCheckOk?[[NSData alloc] initWithBytes:headString.UTF8String length:headString.length]:nil); headString = (rangeCheckOk?nil:[[NSString alloc ]initWithString:headString]); rangeCheckTestComplete = YES; } NSInteger testLength = connectData.length; BOOL isHeader = testLength > 5; if (isHeader) { testLength = (testLength < 128?testLength:128); if (rangeCheckOk) { isHeader = [connectData rangeOfData:headData options:0 range:(NSRange){0,testLength}].location!=NSNotFound; } else { NSString *headStart = [[NSString alloc] initWithBytes:connectData.bytes length:testLength encoding:NSUTF8StringEncoding]; isHeader = [headStart rangeOfString:headString].location!=NSNotFound; [headStart release]; } } return isHeader; }