Solicitar permiso de usuario para recibir UILocalNotifications en iOS 8

Configuré las notificaciones locales en el delegado de la aplicación usando esto:

- (void)applicationDidEnterBackground:(UIApplication *)application { UILocalNotification *notification = [[UILocalNotification alloc]init]; [notification setAlertBody:@"Watch the Latest Episode of CCA-TV"]; [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:5]]; [notification setTimeZone:[NSTimeZone defaultTimeZone]]; [application setScheduledLocalNotifications:[NSArray arrayWithObject:notification]]; } 

Cuando ejecuto la aplicación y luego la dejo, recibo un error que dice:

2014-06-07 11: 14: 16.663 CCA-TV [735: 149070] Intentando progtwigr una notificación local {fecha de activación = sábado, 7 de junio de 2014 a las 11:14:21 Hora del Pacífico, zona horaria = América / Los_Angeles (PDT) offset -25200 (Daylight), repeat interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = sábado, 7 de junio de 2014 a las 11:14:21 Pacific Daylight Time, user info = (null)} con una alerta pero no han recibido permiso del usuario para mostrar alertas

¿Cómo puedo obtener el permiso necesario para mostrar las alertas?

Desde iOS 8, debes pedirle permiso al usuario para que muestre notificaciones desde tu aplicación, esto se aplica tanto a las notificaciones remotas / push como a las locales. En Swift puedes hacerlo así,

Actualización para Swift 2.0

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { // Override point for customization after application launch. if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:"))) { let notificationCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory() notificationCategory.identifier = "INVITE_CATEGORY" notificationCategory.setActions([replyAction], forContext: UIUserNotificationActionContext.Default) //registerting for the notification. application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes:[.Sound, .Alert, .Badge], categories: nil)) } else { //do iOS 7 stuff, which is pretty much nothing for local notifications. } return true } 

Swift 3.2

 if(UIApplication.instancesRespond(to: #selector(UIApplication.registerUserNotificationSettings(_:)))){ let notificationCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory() notificationCategory.identifier = "INVITE_CATEGORY" notificationCategory.setActions([replyAction], forContext: UIUserNotificationActionContext.Default) //registerting for the notification. application.registerUserNotificationSettings(UIUserNotificationSettings(types:[.sound, .alert, .badge], categories: nil)) } else{ //do iOS 7 stuff, which is pretty much nothing for local notifications. } 

La syntax de Objective C también es muy similar.

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]){ [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]]; } // Override point for customization after application launch. return YES; } 

Para verificar los tipos de notificación actualmente registrados, puede usar el método de la clase UIApplication,

 - (UIUserNotificationSettings *)currentUserNotificationSettings 

Por lo tanto, si el usuario ha dicho que no a su aplicación, esta función debe devolver una configuración sin ningún tipo.

He escrito un tutorial sobre esto, puedes verlo aquí .

Ponga este código en el controlador de vista donde primero progtwigrá las notificaciones (si las progtwig en el lanzamiento, entonces será la application:didFinishLaunchingWithOptions: :

 if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) { [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound categories:nil]]; } 

En Swift:

 if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:"))) { UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Alert | .Sound, categories: nil)) } 

Las soluciones que prueban el número de versión del sistema son subóptimas y propensas a errores.

Pruebe esto con Objective-C:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions { // are you running on iOS8? if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound) categories:nil]; [application registerUserNotificationSettings:settings]; } else // iOS 7 or earlier { UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound; [application registerForRemoteNotificationTypes:myTypes]; } } 

Para Swift:

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { // Override point for customization after application launch. if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:"))) { application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, categories: nil)) } else { // } return true } 

Acabo de enfrentar el mismo problema. Parece que en iOS 8 tenemos que hacer un paso adicional, generalmente dentro de:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /*...*/ } 

Puede usar este código si desea mantenerlo compatible con versiones anteriores:

 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) { [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]]; } #endif 

El sistema recordará la decisión y solo preguntará una vez.

** Notificación local con acción de tres botones para iOS8 +

// Botón: LO TOMÉ, RECUERDE MÁS TARDE, PASE **

  let completeAction = UIMutableUserNotificationAction() completeAction.identifier = "COMPLETE_TODO" completeAction.title = "I TOOK IT" completeAction.activationMode = .Background completeAction.destructive = true completeAction.authenticationRequired = false let remindAction = UIMutableUserNotificationAction() remindAction.identifier = "REMIND_TODO" remindAction.title = "REMIND LATER" remindAction.activationMode = .Background remindAction.destructive = false // remindAction.authenticationRequired = false let skipAction = UIMutableUserNotificationAction() skipAction.identifier = "SKIP_TODO" skipAction.title = "SKIP IT" skipAction.activationMode = .Background skipAction.destructive = false skipAction.authenticationRequired = false let todoCategory = UIMutableUserNotificationCategory() todoCategory.identifier = "TODO_CATEGORY" todoCategory.setActions([completeAction, remindAction, skipAction], forContext: .Default) todoCategory.setActions([completeAction,remindAction,skipAction], forContext: .Minimal) if application.respondsToSelector("isRegisteredForRemoteNotifications") { let categories = NSSet(array: [todoCategory,todoVideoCategory]) let types:UIUserNotificationType = ([.Alert, .Sound, .Badge]) let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: categories as? Set) application.registerUserNotificationSettings(settings) application.registerForRemoteNotifications() } }