【问题标题】:FCM push for iOS callback not called未调用 iOS 回调的 FCM 推送
【发布时间】:2019-11-14 08:59:50
【问题描述】:

我对 FCM 推送通知有疑问。

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

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void) 

当我收到推送时不会调用。通知是在我的 iPhone 中生成的。

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)

被调用,但我不明白为什么,因为它已被弃用。

我的通知内容:

{
  "to": "FCM Token",
  "priority": "high",
  "content_available": true,
  "notification": {
    "sound": "default",
    "title": "Test",
    "body": "Test",
    "description": "Test"
  },
  "data": {
    "id": 123456,
    "status": "11",
  }
}

在我的 AppDelegate.swift 中:

import UIKit
import CoreData
import Firebase
import Fabric
import Crashlytics
import GoogleMaps
import GooglePlaces
import FBSDKLoginKit
import GoogleSignIn
import NotificationBannerSwift
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


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

        if #available(iOS 10.0, *) {
          // For iOS 10 display notification (sent via APNS)
          UNUserNotificationCenter.current().delegate = self

          let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
          UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: {_, _ in })
        } else {
          let settings: UIUserNotificationSettings =
          UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
          application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()

        Messaging.messaging().delegate = self
        Messaging.messaging().shouldEstablishDirectChannel = true


        return ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    func applicationWillResignActive(_ application: UIApplication) {
        pprint(" - applicationWillResignActive - ")
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
        AppEvents.activateApp()
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        pprint(" - applicationDidEnterBackground - ")
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
         pprint(" - applicationWillEnterForeground - ")
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        pprint(" - applicationDidBecomeActive - ")
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        pprint(" - applicationWillTerminate - ")
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Unable to register for remote notifications: \(error.localizedDescription)")
    }

    private func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        pprint("apns token: ", deviceToken)
        Messaging.messaging().apnsToken = deviceToken as Data
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // If you are receiving a notification message while your app is in the background,
        // this callback will not be fired till the user taps on the notification launching the application.
        // TODO: Handle data of notification
        // With swizzling disabled you must let Messaging know about the message, for Analytics
         Messaging.messaging().appDidReceiveMessage(userInfo)
        // Print message ID.

        print(" ")
        print("-- New message classique --")
        print("Notification received : \(userInfo)")
        print(" ")

        // Print full message.
        print(userInfo)

        completionHandler(.noData)
    }

 // MARK: - UNUserNotificationCenterDelegate methods
 extension AppDelegate: UNUserNotificationCenterDelegate {

     // FOREGROUND: The method will be called on the delegate only if the application is in the foreground. If the method is not implemented or the handler is not called in a timely manner then the notification will not be presented. The application can choose to have the notification presented as a sound, badge, alert and/or in the notification list. This decision should be based on whether the information in the notification is otherwise visible to the user.
     func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void) {
         DispatchQueue.main.async {
 //            print("will present: ", notification)
 //            Messaging.messaging().appDidReceiveMessage(notification.request.content.userInfo)
 //            completionHandler(.alert)
             let userInfo = notification.request.content.userInfo

             // With swizzling disabled you must let Messaging know about the message, for Analytics
              Messaging.messaging().appDidReceiveMessage(userInfo)

             // Print message ID.
             print(" ")
             print("Notification received : \(notification)")
             print("-- New message from Notification ios10 only --")
             print(" ")

             guard
                 let aps = userInfo[AnyHashable("aps")] as? NSDictionary,
                 let alert = aps["alert"] as? NSDictionary,
                 let body = alert["body"] as? String,
                 let title = alert["title"] as? String
                 else {
                     // handle any error here
                     return
                 }

             print("Title: \(title) \nBody:\(body)")

             let banner = NotificationBanner(title: title, subtitle: body, style: .success)
             banner.show()

             // Change this to your preferred presentation option
             //completionHandler([])
         }
     }

     // BACKGROUND: The method will be called on the delegate when the user responded to the notification by opening the application, dismissing the notification or choosing a UNNotificationAction. The delegate must be set before the application returns from applicationDidFinishLaunching:.
     func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void) {
         DispatchQueue.main.async {
             print("didReceive")
             let userInfo = response.notification.request.content.userInfo
             // Print message ID.
             if let messageID = userInfo["gcmMessageIDKey"] {
               print("Message ID: \(messageID)")
             }
             print(userInfo)
             if let body = userInfo["body"] as? String {
                 print("inbody")
                 NotificationCenter.default.post(name: Notification.Name("userInfo"), object: body)
             }
             //Push().handlePush(info: userInfo)
             // Print full message.
             print(userInfo)
             Messaging.messaging().appDidReceiveMessage(response.notification.request.content.userInfo)
             completionHandler()
         }
     }
 }

 // MARK: - MessagingDelegate methods
 extension AppDelegate: MessagingDelegate {

     func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
         //log.info("FCM registration token received = \(fcmToken)")
         print("FCM registration token received = \(fcmToken)")
         let dataDict:[String: String] = ["token": fcmToken]
         NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
         // TODO: If necessary send token to application server.
         // Note: This callback is fired at each app startup and whenever a new token is generated.
     }

     func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
         //log.info("didReceive message = \(remoteMessage)")
         print("didReceive message = \(remoteMessage)")
     }

     func applicationReceivedRemoteMessage(_ remoteMessage: MessagingRemoteMessage) {
         print(" - - - FIR Remote message - - - ")
         print("%@", remoteMessage.appData)
         //Push().handlePush(info: remoteMessage.appData)
     }
 }

在我的 Info.plist 中,我将 FirebaseAppdelegateProxyEnable 设置为 NO

在功能方面,我启用了推送通知,并且在后台模式下也启用了远程通知。

我使用的是 Xcode 11.1。我已将我的项目转换为 Swift 5(它是使用 Swift 3 创建的),我已将构建系统更改为新的。

我在这个项目中有两个目标,我不知道它是否与我的问题有关。

我尝试使用具有相同 AppDelegate.swift、相同包标识符的空新项目并且它可以工作。

【问题讨论】:

  • 您是否在 didRegisterForRemoteNotificationsWithDeviceToken 中获取 Firebase 令牌?
  • 我在 MessagingDelegate 的 didReceiveRegistrationToken 中获得 Firebase 令牌
  • 我认为你转换的函数代码不同所以请将你的代码放在我的答案函数中并检查它是否被调用?
  • 我不确定,但 shouldEstablishDirectChannel 可能会让 Firebase 直接向您的应用发送消息,而无需通过通常的 Apple 推送通知服务。仅供参考,didReceiveRemoteNotification userInfo: [AnyHashable: Any],当您的应用启用了后台通知和功能时,fetchCompletionHandler completionHandler 仍然是接收后台通知(通知负载中带有 content-available= true 的通知)的默认方式
  • @NicolasManzini 我尝试将其设置为 False,但没有更改。我发现 didReceiveRemoteNotification 已被弃用,将被前台中的 willPresent 和后台中的 didReceive 取代。问题是它适用于我的新应用

标签: ios swift firebase firebase-cloud-messaging


【解决方案1】:

试试这个

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    // put your code here
}

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    // put your code here
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 2021-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多