web-dev-qa-db-fra.com

didReceiveRemoteNotification non appelée, iOS 10

Dans iOS 9.3, la méthode didReceiveRemoteNotification est appelée aux deux occasions suivantes.

1) Lorsque la notification Push est reçue 2) Lorsque l'utilisateur lance l'application en appuyant sur la notification.

Mais sur iOS 10, je remarque que la méthode didReceiveRemoteNotification ne PAS se déclenche lorsque l'utilisateur lance l'application en appuyant sur la notification. Il n'est appelé que lorsque la notification est reçue. Par conséquent, je ne peux plus rien faire après le lancement de l'application à partir de la notification.

Quel devrait être le correctif pour cela? Une idée?

66
smartsanja

tapez converson

enter image description here

pour Swift3

enter image description here

-

pour échantillon voir this

importer le framework UserNotifications et ajouter le UNUserNotificationCenterDelegate dans Appdelegate

import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,UNUserNotificationCenterDelegate  


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    //create the notificationCenter
    let center  = UNUserNotificationCenter.current()
    center.delegate = self
    // set the type as sound or badge
    center.requestAuthorization(options: [.sound,.alert,.badge,  .providesAppNotificationSettings]) { (granted, error) in
        // Enable or disable features based on authorization

        }
        application.registerForRemoteNotifications()

    return true
}


 func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
 // let chars = UnsafePointer<CChar>((deviceToken as NSData).bytes)
  var token = ""

  for i in 0..<deviceToken.count {
//token += String(format: "%02.2hhx", arguments: [chars[i]])
   token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
  }

  print("Registration succeeded!")
  print("Token: ", token)
 }

 func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
  print("Registration failed!")
 }

recevoir les notifications en utilisant ce délégué

 func userNotificationCenter(_ center: UNUserNotificationCenter,  willPresent notification: UNNotification, withCompletionHandler   completionHandler: @escaping (_ options:   UNNotificationPresentationOptions) -> Void) {
    print("Handle Push from foreground")
    // custom code to handle Push while app is in the foreground
    print("\(notification.request.content.userInfo)")
 }

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    print("Handle Push from background or closed")
    // if you set a member variable in didReceiveRemoteNotification, you  will know if this is from closed or background
    print("\(response.notification.request.content.userInfo)")
}

func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
let navController = self.window?.rootViewController as! UINavigationController
let notificationSettingsVC = NotificationSettingsViewController()
navController.pushViewController(notificationSettingsVC, animated: true)
}

pour plus d'informations, vous pouvez voir dans Apple API Référence


objectif C

AppDelegate.h a ces lignes:

Étape 1

//Add Framework in your project "UserNotifications"
#import <UserNotifications/UserNotifications.h>  
@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>  

Étape 2

AppDelegate.m

  // define macro
  #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)  
  #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)  

Étape 3

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
application.applicationIconBadgeNumber = 0;
    if( SYSTEM_VERSION_LESS_THAN( @"10.0" ) ) {  
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound |    UIUserNotificationTypeAlert | UIUserNotificationTypeBadge |  UIUserNotificationTypeprovidesAppNotificationSettings) categories:nil]];  
        [[UIApplication sharedApplication] registerForRemoteNotifications];  

        //if( option != nil )  
        //{  
        //    NSLog( @"registerForPushWithOptions:" );  
        //}  
    } else {  
      UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];  
      center.delegate = self;  
      [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if( !error ) {
            // required to get the app to do anything at all about Push notifications  
            [[UIApplication sharedApplication] registerForRemoteNotifications];
            NSLog( @"Push registration success." );  
        } else {
            NSLog( @"Push registration FAILED" );  
            NSLog( @"ERROR: %@ - %@", error.localizedFailureReason, error.localizedDescription );  
            NSLog( @"SUGGESTIONS: %@ - %@", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );  
        }
        }];
    }

    return YES;
}

Cela se déclenchera à la suite de l'appel de registerForRemoteNotifications:

 - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken  
{  
// custom stuff we do to register the device with our AWS middleman  
 }

Ensuite, lorsqu'un utilisateur appuie sur une notification, cela déclenche:

Cela se déclenche sous iOS 10 lorsque l'application est au premier plan ou en arrière-plan, mais n'est pas fermée

 -(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void  
  (^)(UIBackgroundFetchResult))completionHandler  
  {  
// iOS 10 will handle notifications through other methods  

if( SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO( @"10.0" ) )  
{  
  NSLog( @"iOS version >= 10. Let NotificationCenter handle this one." );  
 // set a member variable to tell the new delegate that this is background  
  return;  
}  
NSLog( @"HANDLE Push, didReceiveRemoteNotification: %@", userInfo );  

// custom code to handle notification content  

if( [UIApplication sharedApplication].applicationState == UIApplicationStateInactive )  
{  
  NSLog( @"INACTIVE" );  
  completionHandler( UIBackgroundFetchResultNewData );  
}  
else if( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground )  
{  
  NSLog( @"BACKGROUND" );  
  completionHandler( UIBackgroundFetchResultNewData );  
}  
else  
{  
  NSLog( @"FOREGROUND" );  
  completionHandler( UIBackgroundFetchResultNewData );  
}  
}  

ou utiliser

  - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo  
{  
[self application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:^(UIBackgroundFetchResult result) {  
}];  
}  

Puis pour iOS 10, ces deux méthodes:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center  
    willPresentNotification:(UNNotification *)notification  
  withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler  
    {  
  NSLog( @"Handle Push from foreground" );  
  // custom code to handle Push while app is in the foreground  
    NSLog(@"%@", notification.request.content.userInfo);
   }  

- (void)userNotificationCenter:(UNUserNotificationCenter *)center  
didReceiveNotificationResponse:(UNNotificationResponse *)response  
  withCompletionHandler:(void (^)())completionHandler  
   {  
     NSLog( @"Handle Push from background or closed" );  
     // if you set a member variable in didReceiveRemoteNotification, you  will know if this is from closed or background  
     NSLog(@"%@", response.notification.request.content.userInfo);
    }  

    - (void)userNotificationCenter:(UNUserNotificationCenter *)center 
   openSettingsForNotification:(UNNotification *)notification{
        Open notification settings screen in app
   }
131
Anbu.Karthik

J'ai eu le même problème. La bannière de notification est apparue, mais la méthode -application:didReceiveRemoteNotification:fetchCompletionHandler: n’a pas été appelée. La solution pour moi qui a fonctionné a été d'ajouter l'implémentation de la méthode - application:didReceiveRemoteNotification: et de transférer l'appel à -application:didReceiveRemoteNotification:fetchCompletionHandler::

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [self application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:^(UIBackgroundFetchResult result){}];
}

Source .

14
Aleksander Grzyb

C'est un bug iOS. Il sera corrigé dans iOS 10.1. Mais attendez la publication de la version 10.1 en octobre au lieu d’implémenter une nouvelle bibliothèque et supprimez-la plus tard.

https://forums.developer.Apple.com/thread/54322

7
Yongxiang Ruan

code Swift:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    if #available(iOS 10.0, *) {
        let center = UNUserNotificationCenter.currentNotificationCenter()
        center.delegate = self
    }

    // ...

    return true
}

@available(iOS 10.0, *)
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {        
    print(response.notification.request.content.userInfo)        
}

@available(iOS 10.0, *)
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    print(notification.request.content.userInfo)
}
6
Adam Bardon

Version de travail iOS 11, Swift 4, Xcode 9. Il suffit de copier-coller le code ci-dessous dans AppDelegate.

import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,UNUserNotificationCenterDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        if #available(iOS 10, *)
        { // iOS 10 support
            //create the notificationCenter
            let center = UNUserNotificationCenter.current()
            center.delegate = self
            // set the type as sound or badge
            center.requestAuthorization(options: [.sound,.alert,.badge]) { (granted, error) in
                if granted {
                    print("Notification Enable Successfully")
                }else{
                    print("Some Error Occure")
                }
            }
            application.registerForRemoteNotifications()
        }
        else if #available(iOS 9, *)
        {
            // iOS 9 support
            UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
            UIApplication.shared.registerForRemoteNotifications()
        }
        else if #available(iOS 8, *)
        {
            // iOS 8 support
            UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound,
                                                                                                     .alert], categories: nil))
            UIApplication.shared.registerForRemoteNotifications()
        }
        else
        { // iOS 7 support
            application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
        }
        return true
    }


    //get device token here
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
        deviceToken: Data)
    {
        let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
        let token = tokenParts.joined()
        print("Registration succeeded!")
        print("Token: ", token)

        //send tokens to backend server
    }

    //get error here
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error:
        Error) {
        print("Registration failed!")
    }

    //get Notification Here below ios 10
    func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
        // Print notification payload data
        print("Push notification received: \(data)")
    }

    //This is the two delegate method to get the notification in iOS 10..
    //First for foreground
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (_ options:UNNotificationPresentationOptions) -> Void)
    {
        print("Handle Push from foreground")
        // custom code to handle Push while app is in the foreground
        print("\(notification.request.content.userInfo)")
    }
    //Second for background and close
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response:UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
    {
        print("Handle Push from background or closed")
        // if you set a member variable in didReceiveRemoteNotification, you will know if this is from closed or background
        print("\(response.notification.request.content.userInfo)")
    }


}
6
Naishta

BTW, ce problème semble être résolu dans iOS 10.1. J'ai testé mon application sur 10.1, tout fonctionne bien

5
smartsanja

Swift 4 et IOS 12.

Bien qu'il puisse y avoir plusieurs raisons (déjà mentionnées dans d'autres réponses) pour expliquer ce problème, dans mon cas, la solution était liée à la charge utile lors de l'envoi de la notification Push:

Vous devez définir la clé "content-available" sur la charge utile json sur 1.

par exemple:

{"aps": {"alert": "Test", "content-available": 1 , "badge" : 1, "son": "par défaut"}}

3
Fidel

Swift 4, Si vous utilisez version de iOS 11 ou xcode supérieure à 9., vous devez avoir la méthode délégué UNUserNotification pour appeler le didReceiveRemoteNotification

  func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

//Your code to handle events

}
0
Hiren Rathod