iOS7 se bloquea cuando se registra para notifications remotas

Esto funciona bien ejecutándose en iOS8, pero cuando lo pongo en un dispositivo iOS7, se bloquea y me da el error

-[UIApplication registerUserNotificationSettings:]: unrecognized selector sent to instance 0x14e56e20 

Me logging para AppDelegate notifications en mi AppDelegate :

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { #ifdef __IPHONE_8_0 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert) categories:nil]; [[UIApplication shanetworkingApplication] registerUserNotificationSettings:settings]; #else //register to receive notifications UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound; [[UIApplication shanetworkingApplication] registerForRemoteNotificationTypes:myTypes]; #endif application.applicationIconBadgeNumber = 0; return YES; } 

Cuando establezco un punto de interrupción, siempre ejecuta el código en el bloque __IPHONE_8_0 . ¿De qué otra forma puedo detectar qué bloque debo ejecutar?

No debería usar el preprocesador como este. Un enfoque mejor es verificar si su object responde al post que le está enviando en lugar de verificar la versión del sistema operativo. Cambia tu método a

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert) categories:nil]; [application registerUserNotificationSettings:settings]; } else { //register to receive notifications UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound; [application registerForRemoteNotificationTypes:myTypes]; } application.applicationIconBadgeNumber = 0; return YES; } 

Un par de cosas para notar aquí. Cambié [UIApplication shanetworkingApplication] a la application porque el delegado ya está pasando en su instancia UIApplication , así que simplemente acceda directamente.

NSObject respondsToSelector: es un método de NSObject que le dirá si un receptor, la application , responderá a un selector (o método). Solo necesita ajustar el método como @selector(myMethod:) para comprobarlo. Esta es una buena práctica para get compatibilidad con versiones anteriores al utilizar APIs más nuevas. También desearía hacer este tipo de comprobación cuando se trate de objects anónimos de tipo id .

En cuanto a por qué el #ifdef __IPHONE_8_0 no funcionó, echa un vistazo a esta respuesta: https://stackoverflow.com/a/25301879/544094

#ifdef __IPHONE_8_0 es una directiva de time de compilation . Debido a que su objective de compilation generalmente será la última versión de iOS, este siempre será el código que se comstack en su aplicación. Esto es independiente del dispositivo en el que se ejecuta la aplicación, tal como se hace antes de que la aplicación exista (definitivamente antes de ejecutar la aplicación).

En su lugar, debería usar una comprobación de time de ejecución . Puede verificar la versión de iOS, o simplemente puede verificar la existencia de los methods que está intentando usar:

 if ([[UIApplication shanetworkingApplication] respondsToSelector:@selector(registerUserNotificationSettings)]) { // Do iOS8+ stuff. } else { // Do iOS7- stuff. }