iOS7 et iOS8: comment détecter quand l'user a répondu Non à une request de notifications push

Je construis une application qui cible iOS7 et iOS8. Je request à l'user la permission d'envoyer des notifications push. Mais pour une raison quelconque, ni iOS7 ni iOS8 n'appelle jamais mon gestionnaire d' application:didFailToRegisterForRemoteNotificationsWithError si je clique sur "Non" lorsqu'on lui request l'autorisation push.

Ma question: comment puis-je savoir, sur iOS7 et iOS8, lorsque l'user a rejeté la request de notifications push – et comment puis-je savoir si ils ont refusé la request?

J'ai regardé un tas de réponses StackOverflow et j'ai implémenté ce qu'ils suggèrent, mais ça ne fonctionne pas comme documenté:

  • iOS7: si l'user approuve la request, le système appelle mon application:didRegisterForRemoteNotificationsWithDeviceToken: handler. Donc je peux dire qu'ils l'ont approuvé. Mais si l'user refuse la request, je n'obtiens pas de callback à l' application:didFailToRegisterForRemoteNotificationsWithError . Cela semble être un bug, et je ne peux pas dire que l'user a refusé la request.
  • iOS8: si l'user approuve ou refuse la request, le système appelle mon application:didRegisterUserNotificationSettings gestionnaire de application:didRegisterUserNotificationSettings . Je peux regarder le paramètre notificationSettings pour voir si l'user a approuvé ou refusé ma request, c'est donc pratique. Toutefois, si j'appelle par la suite isRegisteredForRemoteNotifications() (par exemple, lorsque l'application devient active plus tard), elle renvoie toujours true, même si l'user a refusé la request . Donc, je reçois un faux positif. Cela semble être un bug et je vois que d' autres ont remarqué cela aussi . Mise à jour: si j'appelle par la suite let settings = UIApplication.sharedApplication().currentUserNotificationSettings() , je peux vérifier settings.types pour voir si les alertes sont autorisées. Donc, pour iOS8, il semble que je suis tout set.

J'utilise un boolean NSUserDefaults pour savoir si j'ai déjà demandé à l'user d'accorder l'autorisation.

J'utilise des périphériques matériels pour tester (iPhone 4S avec iOS7 et iPhone 5 avec iOS8), pas un simulateur.

Je réinitialise mon appareil après chaque test , pour que l'alerte de request s'affiche à nouveau.

Voici comment je m'enregistre pour les notifications push. La twig if est prise sur iOS8 et la twig else est prise sur iOS7:

  let application = UIApplication.sharedApplication() if (application.respondsToSelector("registerUserNotificationSettings:")) { let settings = UIUserNotificationSettings(forTypes: .Badge | .Alert | .Sound, categories: nil ) application.registerUserNotificationSettings(settings) } else { application.registerForRemoteNotificationTypes(.Badge | .Alert | .Sound) } 

(Dans iOS8, lorsque l' application:didRegisterUserNotificationSettings: est appelée, j'appelle ensuite application.registerForRemoteNotifications() ).

Votre méthode didFailToRegisterForRemoteNotificationsWithError n'est pas appelée, car l'inscription n'a pas échoué – elle n'a jamais été tentée car l'user a refusé la requête.

Sur iOS7, vous pouvez faire quelques choses:

  1. Supposons que les notifications à distance ne sont pas disponibles tant que didRegisterForRemoteNotificationsWithDeviceToken n'est pas appelé
  2. Vérifiez la valeur enabledRemoteNotificationTypes sur l'object UIApplication

J'essayais de find un moyen de contourner ce même problème.

Lorsque l'autorisation de notification push UIAlert est affichée, elle est affichée depuis l'extérieur de mon application. Une fois que l'user a sélectionné "Ne pas autoriser" ou "OK", mon application redevient active.

J'ai un controller de vue que je présente avant d'inviter l'user pour les permissions Push. Dans cette vue, j'écoute UIApplicationDidBecomeActiveNotification , puis je rejette mon controller de vue.

Cela a fonctionné assez bien, alors que toutes les autres solutions que j'ai vues n'ont pas fonctionné pour moi du tout.

En supposant que vous comstackz sur iOS8 ou plus récent, vous pouvez utiliser la méthode de délégation suivante:

 func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) { print("Notifications status: \(notificationSettings)") } 

puis sur votre didFinishLaunching (ou là où est approprié pour vos besoins) vous devez invoquer:

 let app = UIApplication.sharedApplication() let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil) app.registerUserNotificationSettings(settings) app.registerForRemoteNotifications() 

À ce stade, vos users seront invités avec un message d'invite Autoriser / Ne pas autoriser. Quel que soit le choix de votre user, vous recevrez un appel à la méthode ci-dessus, permettant une configuration fine de votre application. Le résultat sera quelque chose comme:

 Notification Status: <UIUserNotificationSettings: 0x7fa261701da0; types: (none);> Notification Status: <UIUserNotificationSettings: 0x7ff032e21dd0; types: (UIUserNotificationTypeAlert UIUserNotificationTypeBadge UIUserNotificationTypeSound);> 

Dans le premier cas, vous remarquerez que l'user a refusé les notifications. Le second concerne l'option allow.