didReceiveRemoteNotification nicht aufgerufen, iOS 10

75

In iOS 9.3 wird die didReceiveRemoteNotificationMethode bei beiden folgenden Gelegenheiten aufgerufen.

1) Wenn die Push-Benachrichtigung empfangen wird 2) Wenn der Benutzer die App durch Tippen auf die Benachrichtigung startet.

Unter iOS 10 stelle ich jedoch fest, dass die didReceiveRemoteNotificationMethode NICHT ausgelöst wird, wenn der Benutzer die App durch Tippen auf die Benachrichtigung startet. Es wird nur aufgerufen, wenn die Benachrichtigung empfangen wird. Daher kann ich keine weiteren Aktionen ausführen, nachdem die App von der Benachrichtigung aus gestartet wurde.

Was sollte das Problem beheben? Irgendeine Idee?

Smartsanja
quelle
Arbeiten mit ObjC oder Swift
Gurmandeep
Dies könnte dann helfen, stackoverflow.com/questions/31450403/…
gurmandeep

Antworten:

135

Typ Converson

Geben Sie hier die Bildbeschreibung ein

für Swift3

Geben Sie hier die Bildbeschreibung ein

- -

Beispiel siehe hier

Importieren Sie das UserNotificationsFramework und fügen Sie das UNUserNotificationCenterDelegatein Appdelegate hinzu

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!")
 }

Erhalten Sie die Benachrichtigungen mit diesen Delegaten

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

Weitere Informationen finden Sie in der Apple API- Referenz


Ziel c

AppDelegate.h hat folgende Zeilen:

Schritt 1

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

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

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

Dies wird durch den Aufruf von registerForRemoteNotifications ausgelöst:

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

Wenn ein Benutzer auf eine Benachrichtigung tippt, wird Folgendes ausgelöst:

Dies wird in iOS 10 ausgelöst, wenn sich die App im Vordergrund oder im Hintergrund befindet, aber nicht geschlossen ist

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

oder verwenden

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

Dann für iOS 10 diese beiden Methoden:

- (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
   }
Anbu.Karthik
quelle
15
Bitte veröffentlichen Sie Antworten nicht über mehrere Fragen hinweg erneut. Jede Antwort sollte auf die jeweilige Frage zugeschnitten sein, und Fragen sollten gegebenenfalls als Duplikate gekennzeichnet werden.
Matt
1
Sie müssen keine Berechtigungen über UserNotificationCenter anfordern. Die Registrierung als Delegierter reicht aus, um das Problem zu beheben.
Phatmann
2
Entschuldigung, wie kann ich userInfo erhalten, wenn ich didReceive Notification erhalte?
Svitlana
3
@Svitlana - Sie können hier NSLog erhalten (@ "% @", response.notification.request.content.userInfo);
Anbu.Karthik
Nicht tun Sie müssen auch „Remote Benachrichtigungen“ von ermöglichen Hintergrund Modi . Ich bin tatsächlich ein bisschen verwirrt über den Unterschied zwischen dem Aktivieren von "Push-Benachrichtigungen", wie in Ihrem Bild gezeigt, und "Remote-Benachrichtigungen", wie hier gezeigt . Was passiert, wenn ich nur das tue, was Sie gesagt haben, und keine "Remote-Benachrichtigungen" aktiviere?
Honey
15

Ich hatte das gleiche Problem. Das Benachrichtigungsbanner wurde angezeigt, die -application:didReceiveRemoteNotification:fetchCompletionHandler:Methode wurde jedoch nicht aufgerufen. Die Lösung für mich bestand darin, die Implementierung der - application:didReceiveRemoteNotification:Methode hinzuzufügen und den Aufruf an -application:didReceiveRemoteNotification:fetchCompletionHandler:folgende Adresse weiterzuleiten :

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

Quelle .

Aleksander Grzyb
quelle
13

Swift 4 und IOS 12.

Obwohl es mehrere Gründe geben kann (bereits in anderen Antworten erwähnt), warum dieses Problem auftreten könnte, hing die Lösung in meinem persönlichen Fall mit der Nutzlast beim Senden der Push-Benachrichtigung zusammen:

Sie müssen den Schlüssel "Inhalt verfügbar" auf dem JSON festlegen Nutzlast auf 1.

zB:

{"aps": {"alert": "Test", "content-available": 1 , "badge": 1, "sound": "default"}}

Fidel
quelle
8

Schneller Code :

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)
}
Adam Bardon
quelle
7

Arbeitsversion iOS 11, Swift 4, Xcode 9 . Kopieren Sie einfach den folgenden Code und fügen Sie ihn in AppDelegate ein.

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)")
    }


}
Naishta
quelle
Sie rufen application.registerForRemoteNotifications () auf und warten nicht auf requestAuthorization. Ist es o.k?
Shivam Pokhriyal
6

Es ist ein iOS-Fehler. Es wird in iOS 10.1 behoben. Warten Sie jedoch auf die Veröffentlichung von 10.1 im Oktober, anstatt eine neue Bibliothek zu implementieren, und entfernen Sie sie später.

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

Yongxiang Ruan
quelle
5

Übrigens scheint dieses Problem in iOS 10.1 behoben zu sein. Ich habe meine App auf 10.1 getestet, alle funktionieren einwandfrei

Smartsanja
quelle
1

Swift 4: Wenn Sie eine iOS 11- oder Xcode-Version größer als 9.0 verwenden , müssen Sie die Delegierungsmethode UNUserNotification verwenden, um die didReceiveRemoteNotification aufzurufen

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

//Your code to handle events

}
Hiren Rathod
quelle