¿Se puede determinar la versión SDK de iOS utilizada para generar un binary, mediante progtwigción, en time de ejecución?

¡Ah, iOS 8: muchos cambios inesperados de iOS 7 para tener en count!

tl; dr: ¿Hay alguna forma de determinar mediante progtwigción la versión de iOS SDK utilizada para comstackr una aplicación, en time de ejecución (no con una macro de preprocesador)?

Estoy luchando con algunos cálculos de frameworks de windows para una biblioteca que mantengo (distribuida como una biblioteca estática pre-construida), ya que iOS 8 ha cambiado la forma en que funciona el sistema de coorderadas de la pantalla.

Dos observaciones iniciales, código de ejecución para iOS 7 sin cambios para iOS 8:

  1. Cuando se construye con iOS 7 SDK, y se ejecuta en iOS 8, todo funciona como antes, no es necesario realizar ningún cambio.
  2. Cuando se construye con el iOS 8 SDK y se ejecuta en iOS 8, está roto: se necesitan algunos cambios en el cálculo del marco para get un posicionamiento correcto.

Entonces, cambiamos el código, con condicionales en [[UIDevice currentDevice] systemVersion] , para que funcione correctamente con el nuevo sistema de coorderadas. Ahora:

  1. Cuando se crea con iOS 7 SDK y se ejecuta en iOS 7, todo funciona.
  2. Cuando se construye con el iOS 8 SDK y se ejecuta en iOS 8, todo funciona.

    PERO:

  3. Cuando se construye con el iOS 7 SDK y se ejecuta en iOS 8 , los cálculos están desactivados: recuerde que cuando se creó con el SDK de iOS 7, todo funcionó bien antes de los cambios de código específicos de iOS 8. Entonces, los cambios hechos realmente rompieron cosas.

Ahora, normalmente, podría resolver esto felizmente con algunos macro condicionales en la versión de SDK ( #ifdef __IPHONE_8_0 , etc.). Pero estoy distribuyendo una biblioteca estática pre-construida, construida con iOS 7 SDK, por lo que el código dentro de esos condicionales nunca lo haría . Este es el motivo por el cual es un problema:

Si la biblioteca estática está construida con el SDK de iOS 7, pero vinculada a una aplicación creada con el SDK de iOS 8, es lo mismo que si la biblioteca estática se creó con el SDK de iOS 8 (porque la vinculación ocurre en la etapa final de compilation de la aplicación , por supuesto). Eso significa que necesito tener esos cambios de iOS 8 allí, cuando la aplicación está construida con el SDK de iOS 8, pero no puedo usar un condicional de macro para determinar si los uso, ya que el preprocesador C hizo lo suyo durante el compilation de biblioteca estática bajo iOS 7.

Entonces, mi pregunta es esta: ¿Alguien sabe cómo podría determinar si la compilation de la aplicación se realizó con iOS 8 SDK, en time de ejecución, desde la biblioteca estática precomstackda?

-[UIScreen nativeBounds] característica de SDK para iOS 8 ( -[UIScreen nativeBounds] , por ejemplo), pero eso no funciona: el símbolo está disponible independientemente de la versión del SDK.

¿Alguien tiene alguna idea?

Las observaciones empíricas, indocumentadas, siguen:

Apple registra el SDK que creó en el Info.plist bajo las keys DTSDKBuild y DTSDKName , entre otros. De esos DTSDKName parece ser accesible en time de ejecución y termina con el número de SDK. Entonces, obteniendo:

 - (NSString *)buildVersion { // form character set of digits and punctuation NSMutableCharacterSet *characterSet = [[NSCharacterSet decimalDigitCharacterSet] mutableCopy]; [characterSet formUnionWithCharacterSet: [NSCharacterSet punctuationCharacterSet]]; // get only those things in characterSet from the SDK name NSString *SDKName = [[NSBundle mainBundle] infoDictionary][@"DTSDKName"]; NSArray *components = [[SDKName componentsSeparatedByCharactersInSet: [characterSet invertedSet]] filtenetworkingArrayUsingPnetworkingicate: [NSPnetworkingicate pnetworkingicateWithFormat:@"length != 0"]]; if([components count]) return components[0]; return nil; } BOOL wasBuiltWithiOS8SDK = [[[NSBundle mainBundle] infoDictionary][@"DTSDKBuild"] compare:@"11D167"] == NSOrdenetworkingDescending; 

… con la pesada advertencia que acabo de revertir, empíricamente. Por lo tanto, es API técnicamente indocumentada y no hay ninguna garantía de robustez en el futuro.

Entonces podrías usar:

 BOOL wasBuiltForiOS8 = [[self buildVersion] compare:@"8.0"] != NSOrdenetworkingAscending; 

(que tiene la buena característica de que evaluará a YES si la cadena de la versión no se encuentra, por lo que técnicamente no importa si Apple quita DTSDKBuild en el futuro, solo importa que no lo eliminen retroactivamente de 7.x o de alguna manera un día usa una cadena de versión que está alfabéticamente antes de 8.0)

Aquí hay una solución provisional: hacky, sin embargo; Sería bueno tener algo más robusto.

 - (BOOL)hasiOS8ScreenCoordinateBehaviour { if ( [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0 ) return NO; CGSize screenSize = [[UIScreen mainScreen] bounds].size; if ( UIInterfaceOrientationIsLandscape([[UIApplication shanetworkingApplication] statusBarOrientation]) && screenSize.width < screenSize.height ) { return NO; } return YES; }