application: didReceiveRemoteNotification: fetchCompletionHandler:
est différent de
application: didReceiveRemoteNotification:
Comment? des docs:
Contrairement à l'application: didReceiveRemoteNotification: method, qui est appelé uniquement lorsque votre application est en cours d'exécution, le système appelle cette méthode quel que soit l'état de votre application. Si votre application est suspendue ou non En cours d’exécution, le système réveille ou lance votre application et la place dans le fichier arrière-plan en cours d'exécution avant d'appeler la méthode. Si l'utilisateur ouvre votre application depuis l'alerte affichée par le système, le système appelle cette méthode à nouveau pour que vous sachiez quelle notification l'utilisateur a sélectionnée.
Mon problème est le suivant: je veux savoir si la méthode a été appelée par l'utilisateur en appuyant sur une alerte affichée par le système à partir du Centre de notifications ou sur une notification Push silencieuse qui réveille le périphérique. Actuellement, autant que je sache, il n’existe aucun moyen évident de se différencier.
- (BOOL)application: didFinishLaunchingWithOptions:
Suivre les launchOptions dans la méthode ci-dessus n'est pas une solution, car elle n'est appelée que si l'application est suspendue/ne s'exécute pas en arrière-plan. Si cela fonctionne en arrière-plan, il n'est pas appelé.
Les documents Apple sont un peu déroutants
application: didReceiveRemoteNotification: fetchCompletionHandler:
est utilisé si votre application prend en charge le mode d'arrière-plan de notification à distance (c'est-à-dire que vous utilisez BackgroundFetch.)
application: didReceiveRemoteNotification:
est appelé lorsque le système d'exploitation reçoit une notification à distance et que l'application est en cours d'exécution (en arrière-plan/suspendue ou au premier plan.)
Vous pouvez vérifier le UIApplicationState pour voir si l'application a été mise au premier plan par l'utilisateur (en appuyant sur la notification) ou était déjà en cours d'exécution lorsque la notification arrive.
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UIApplicationState state = [application applicationState];
// user tapped notification while app was in background
if (state == UIApplicationStateInactive || state == UIApplicationStateBackground) {
// go to screen relevant to Notification content
} else {
// App is in UIApplicationStateActive (running in foreground)
// perhaps show an UIAlertView
}
}
Vous pouvez vérifier la UIApplication
de la applicationState
pour distinguer les appels silencieux des appels passés avec l'application activement utilisée par l'utilisateur:
typedef enum : NSInteger {
UIApplicationStateActive,
UIApplicationStateInactive,
UIApplicationStateBackground
} UIApplicationState;
Ou laissez votre propre drapeau défini sur le applicationDidEnterBackground:
du delegate
.
L'état de l'application n'est pas fiable car si le centre de contrôle ou le centre de notification d'Apple est ouvert sur l'application, application: didReceiveRemoteNotification: fetchCompletionHandler: sera appelée et l'état de l'application sera inactif.
J'ai le même problème en essayant de répondre à un clic sur la notification alors que l'application est en arrière-plan et il ne semble pas y avoir de moyen fiable de l'identifier uniquement.
Lorsque la méthode application: didReceiveRemoteNotification:fetchCompletionHandler:
est appelée application, l'état est UIApplicationStateInactive
si l'utilisateur appuie sur une alerte (dans ce cas, vous souhaitez préparer une interface utilisateur) et UIApplicationStateBackground
lorsque l'application est activée en mode veille (dans ce cas, vous ne chargez que des données).
En cas de Swift
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
let state : UIApplicationState = application.applicationState
if (state == .Inactive || state == .Background) {
// go to screen relevant to Notification content
} else {
// App is in UIApplicationStateActive (running in foreground)
}
}
Pour Swift: Dans application(_:didFinishLaunchingWithOptions:)
, analysez les options de l'application. S'ils existent, vous savez que l'application a été lancée à partir d'eux.
if let remoteNotif = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: Any] {
print("Remote notfi is \(remoteNotif)")
if let notification = remoteNotif["aps"] as? [AnyHashable : Any] {
/// - parse notification
}
}
Sinon, vous pouvez gérer le robinet, et vous savez que l'application est ouverte/arrière-plan/inactiveapplication(_:didReceiveRemoteNotification:fetchCompletionHandler:)
Dans iOS 10.0+, vous pouvez utiliser la méthode
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler;
pour détecter quand l'utilisateur appuie sur une alerte affichée par le système dans NotificationCenter.
Si vous implémentez la méthode ci-dessus
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
sera appelé seulement quand une notification est reçue- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler;
sera appelé lorsque l'utilisateur appuiera sur une notification