Demander l'autorisation de l'utilisateur pour recevoir des notifications UILocal dans iOS 8


115

J'ai configuré des notifications locales dans le délégué d'application en utilisant ceci:

- (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]];
}

Lorsque j'exécute l'application, puis que je la quitte, je reçois une erreur disant:

2014-06-07 11: 14: 16.663 CCA-TV [735: 149070] Tentative de planification d'une notification locale {fire date = samedi 7 juin 2014 à 11:14:21 Pacific Daylight Time, time zone = America / Los_Angeles (PDT) offset -25200 (Daylight), intervalle de répétition = 0, nombre de répétitions = UILocalNotificationInfiniteRepeatCount, prochaine date d'incendie = samedi 7 juin 2014 à 11:14:21 Pacific Daylight Time, user info = (null)} avec une alerte mais n'ont pas reçu la permission de l'utilisateur d'afficher des alertes

Comment puis-je obtenir l'autorisation nécessaire pour afficher les alertes?


1
Je pense que l'application a rejeté l'autorisation une fois, vous pouvez essayer d'activer à partir des paramètres. Mais au fait, UILocalNotification n'a pas besoin de la permission de l'utilisateur ..
— iphonic

Essayez registerUserNotificationSettings. Si cela avait été iOS 8, ce fil aurait répondu à votre question. Mais, allez-y, jetez un œil - stackoverflow.com/questions/24006998/…
— raurora

Réponses:


237

Depuis iOS 8, vous devez demander l'autorisation de l'utilisateur pour afficher les notifications de votre application, cela s'applique à la fois aux notifications à distance / push et locales. Dans Swift, vous pouvez le faire comme ça,

Mise à jour pour 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 syntaxe Objective C est également très similaire.

- (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;
}

Pour vérifier les types de notification actuellement enregistrés, vous pouvez utiliser la méthode de la classe UIApplication,

- (UIUserNotificationSettings *)currentUserNotificationSettings

Donc, si l'utilisateur a dit non à votre application, cette fonction devrait renvoyer un paramètre sans aucun type.

J'ai écrit un tutoriel à ce sujet, vous pouvez le voir ici .


1
Si l'utilisateur refuse l'autorisation, comment déterminez-vous cela ultérieurement par programme?
— jjxtra

@satheeshwaran Quand j'utilise ce code, cela fonctionne bien avec le simulateur avec iOS8. Je voulais la cible de déploiement de mon application à partir d'iOS7. Alors, quand je lance ce code sur un appareil iOS 7, je reçois cette erreur: dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings. Existe-t-il un autre moyen dans Swift de demander à l'utilisateur des autorisations afin de travailler dans iOS7? veuillez aider.
— Raghavendra

@Raghav UIUserNotificationSettings n'est disponible qu'à partir d'iOS 8 et ce à quoi vous êtes confronté est le bon comportement. Vous ne devriez pas utiliser cela dans iOS 7.
— Satheeshwaran

1
-1 pour vérifier la version iOS UIDevice. La réponse stackoverflow.com/a/25735175/1226304 a une meilleure approche pour ce faire.
— derpoliuk

3
@derpoliuk Mise à jour comme dans la réponse pour le bénéfice de tous, ok ??
— Satheeshwaran

38

Mettez ce code dans le contrôleur de vue où vous programmerez d'abord les notifications (si vous les programmez au lancement, alors ce sera application:didFinishLaunchingWithOptions:):

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

Dans Swift:

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

Les solutions qui testent par rapport au numéro de version du système sont sous-optimales et sujettes aux erreurs.


J'utiliserais application.respondsToSelector(Selector("registerUserNotificationSettings"))etif ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
— derpoliuk

7
Eh bien, c'est seulement parce que vous l'utilisez à l'intérieur, application:didFinishLaunchingWithOptions:ce qui fournit un applicationobjet pratique :)
— KPM

18

Essayez ceci pour 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];
  }
}

Pour 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

J'ai juste fait face au même problème. On dirait que dans iOS 8, nous devons faire une étape supplémentaire, généralement effectuée à l'intérieur:

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

Vous pouvez utiliser ce code si vous souhaitez le garder compatible avec les versions antérieures:

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

Le système se souviendra de la décision et ne demandera qu'une seule fois.


Mieux vaut vérifier la version iOS avec ce code si ([[UIDevice currentDevice] .systemVersion floatValue] <10)
— Mehul Chuahan

1

** Notification locale avec action à trois boutons pour iOS8 +

// Bouton: JE L'AI PRIS, RAPPELER PLUS TARD, SAUTER **

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

        }

    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.