DEV Community

David Rickard
David Rickard

Posted on

Data-only FCM push messages on iOS SwiftUI

I was able to figure out how to send data-only FCM push messages to SwiftUI after assembling a bunch of scattered bits of information.

The FCM on iOS guide is a good place to start. Do everything there and come back here to fill in the cracks and finish the data notification implementation.

You'll notice that for SwiftUI it asks you to set FirebaseAppDelegateProxyEnabled to NO in Info.plist. In modern XCode projects this won't be an actual file called Info.plist, it will be the "Info" tab under the your target in the project settings. Also, uncomment all the "if disabling method swizzling" in the example code.

You won't need to call UNUserNotificationCenter.requestAuthorization() to get data messages, only to fire notifications if you decide to when acting on them.

Capabilities

Under Signing and Capabilities in your project you'll need Background Modes -> Remote notifications checked, and Push Notifications added.

Sending messages from the server

After sending your device's FCM token to the server, you can fire off the data messages by calling the FCM v1 HTTP endpoint:

POST https://fcm.googleapis.com/v1/projects/<project_id>/messages:send

{
    "message": {
        "data": {
            "your": "data"
        },
        "token": "abc_def",
        "apns": {
            "headers": {
                "apns-push-type": "background",
                "apns-priority": "5",
                "apns-topic": "com.example.MyApp"
            },
            "payload": {
                "aps": {
                    "content-available": 1
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

token: Your FCM token
apns-topic: Your app's bundle ID

This instructs FCM to create the appropriate request for APNs, as documented in Generating a remote notification.

The apns-push-type header tells it that it can arrive in the background. The apns-priority is 5 because that's required for background notifications. content-available in the payload tells it that it will not be accompanied by any notification, so we don't have any alert, sound or badge keys in the payload.

Handling the messages

I ended up getting the messages on the async method from the example:

func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
      -> UIBackgroundFetchResult 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)