Receive Push Messages

The iOS SDK can receive push messages through FCM (which uses APNs). To set up a Firebase Project to user FCM, refer to the FCM iOS documentation and follow it completely. Make sure to also configure APNs with FCM.

Once you have done that, add your GoogleService-Info.plist to the root of your xcode project.

To register your FCM token with Mitter, do the following:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print("APNs token retrieved: \(deviceToken.base64EncodedString())")

    InstanceID.instanceID().instanceID { (result, error) in
        if let error = error {
            print("Error fetching remote instange ID: \(error)")
        } else if let result = result {
            print("Remote instance ID token: \(result.token)")

            self.mitter.registerFcmToken(token: result.token) {
                result in
                switch result {
                case .success(let deliveryEndpoint):
                    print("Endpoint is: \(deliveryEndpoint.serializedEndpoint)")
                case .error:
                    print("Unable to register endpoint!")
                }
            }
        }
    }

    // With swizzling disabled you must set the APNs token here.
    // Messaging.messaging().apnsToken = deviceToken
}

To receive Messages when the app is in the background and then add it into the Channel view, do the following:

@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {

    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo

        let messageString = userInfo["data"] as! String
        let messagingPipelinePayload = mitter.parseFcmMessage(data: messageString)

        processFcmMessage(pipelinePayload: messagingPipelinePayload)

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

To receive messages directly from FCM (and not via APNs push), do the following:

extension AppDelegate : MessagingDelegate {
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(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.
    }
    // [END refresh_token]
    // [START ios_10_data_message]
    // Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground.
    // To enable direct data messages, you can set Messaging.messaging().shouldEstablishDirectChannel to true.
    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
        print("Received data message: \(remoteMessage.appData)")
        let messagingPipelinePayload = mitter.parseFcmMessage(data: remoteMessage.appData["data"] as! String)
        processFcmMessage(pipelinePayload: messagingPipelinePayload)
    }
    // [END ios_10_data_message]
}

Here is the function (used in the above snippets) that will add the parsed FCM message into the Channel View. Add it to your AppDelegate. Refer to the upcoming sections on the structure of the storyboard and ChannelWindowViewController:

func processFcmMessage(pipelinePayload: MessagingPipelinePayload?) {
    if mitter.isMitterMessage(pipelinePayload) {
        let payload = mitter.processPushMessage(pipelinePayload!)

        switch payload {
            // Handle the new message payload: Add it to the Channel Window View Controller
            case .NewMessagePayload(let message, let channelId):
                if let navController = window?.rootViewController as? UINavigationController {
                    // Get the second controller, which is the ChannelWindowViewController according to the storyboard
                    if let channelWindowViewController = navController.viewControllers[1] as? ChannelWindowViewController {
                        channelWindowViewController.newMessage(channelId: channelId.domainId, message: message)
                    }
                }
            // Ignore all other payloads
            default:
                print("Nothing to print!")
        }
    }
}

Last updated