Solicite permiso de usuario para recibir notificaciones UILocal en iOS 8


115

He configurado 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 salgo, recibo un error que dice:

2014-06-07 11: 14: 16.663 CCA-TV [735: 149070] Intentando programar una notificación local {fecha de incendio = sábado, 7 de junio de 2014 a las 11:14:21 hora de verano del Pacífico, zona horaria = América / Los_Angeles (PDT) offset -25200 (luz del día), intervalo de repetición = 0, recuento de repetición = UILocalNotificationInfiniteRepeatCount, próxima fecha de incendio = sábado, 7 de junio de 2014 a las 11:14:21 hora de verano del Pacífico, información del usuario = (nulo)} con una alerta pero no he recibido permiso del usuario para mostrar alertas

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


1
Creo que la aplicación ha rechazado el permiso una vez, puede intentar habilitarlo desde Configuración. Pero, por cierto, UILocalNotification no necesita permiso del usuario ..
— iphonic

Prueba registerUserNotificationSettings. Si hubiera sido iOS 8, este hilo habría respondido a su pregunta. Pero, adelante, echa un vistazo - stackoverflow.com/questions/24006998/…
— raurora

Respuestas:


237

Dado que iOS 8 debe pedir permiso al usuario para mostrar notificaciones de su aplicación, esto se aplica tanto para notificaciones remotas / push como 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 sintaxis 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 registrados actualmente, puede usar el método de la clase UIApplication,

- (UIUserNotificationSettings *)currentUserNotificationSettings

Entonces, si el usuario ha dicho que no a su aplicación, esta función debería devolver una configuración sin ningún tipo en ella.

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


1
Si el usuario niega el permiso, ¿cómo se determina esto más tarde mediante programación?
— jjxtra

@satheeshwaran Cuando uso este código, funciona bien con el simulador con iOS8. Quería el objetivo de implementación de mi aplicación a partir de iOS7. Por lo tanto, cuando ejecuta este código en un dispositivo iOS7, me sale este error: dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings. ¿Hay alguna otra forma en Swift de solicitar permisos al usuario para trabajar en iOS7? por favor ayuda.
— Raghavendra

@Raghav UIUserNotificationSettings solo está disponible desde iOS 8 y lo que enfrenta es el comportamiento correcto. No deberías usar esto en iOS 7.
— Satheeshwaran

1
-1 para comprobar la versión de iOS UIDevice. stackoverflow.com/a/25735175/1226304 answer tiene un mejor enfoque para hacer esto.
— Derpoliuk

3
@derpoliuk Actualizado como en la respuesta para el beneficio de todos, ¿ok ??
— Satheeshwaran

38

Coloque este código en el controlador de vista donde primero programará las notificaciones (si las programa en el lanzamiento, entonces será 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 se prueban con el número de versión del sistema son subóptimas y propensas a errores.


Me gustaría utilizar application.respondsToSelector(Selector("registerUserNotificationSettings"))yif ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
— derpoliuk

7
Bueno, eso es solo porque lo está usando en el interior, lo application:didFinishLaunchingWithOptions:que proporciona un applicationobjeto útil :)
— KPM

18

Pruebe esto para 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
}

5

Simplemente enfrenté el mismo problema. Parece que en iOS 8 necesitamos hacer un paso adicional, generalmente se hace en el interior:

- (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.


Es mejor verificar la versión de iOS con este código si ([[UIDevice currentDevice] .systemVersion floatValue] <10)
— Mehul Chuahan

1

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

// Botón: LO TOMÉ, RECUERDA MÁS TARDE, SALTÉLO **

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

            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()

        }

    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.