Enable push notifications in a native iOS app

A guide for apps built using Swift and SwiftUI

This guide walks you through enabling push notifications in your iOS app using the Acoustic Connect SDK. The SDK supports push delivery tracking — including notifications dismissed before the app opens — and rich media images such as banner thumbnails and expanded images.

📘

Prerequisites

You must have an Apple Developer Program membership. Push notifications require a paid account. Required role: Account Holder or Admin.

Overview

  1. You — generate an APNs authentication key and share your push notification credentials with your Connect administrator
  2. Connect administrator — uploads your APNs credentials to Connect and sends you the app key and collector URL
  3. You — integrate the Connect SDK using the app key and collector URL
  4. You — configure push notifications in the Apple Developer portal
  5. You — configure push notifications in Xcode
  6. You — add code to request notification permission from your users

Step 1: Get an APNs authentication key

Connect uses token-based APNs authentication. A single .p8 key works across all apps in your team.

  1. In your Apple Developer account, go to Program resources > Certificates, IDs & Profiles > Keys.
  2. Add a new key. Enter a name (for example, "Acoustic Connect APNs") and enable Apple Push Notifications service (APNs) for it.
  1. Click Continue > Register.
  2. Download the .p8 file.
🚧

Warning

Apple only allows you to download the .p8 file once. Save it before proceeding.

Step 2: Share push notification credentials with your Connect administrator

Share the following with your Connect administrator so they can register your app's push notification credentials in Connect. They will send you back the app key and collector URL you need for the next step.

CredentialWhere to find it
Encryption keyThe .p8 file you just downloaded
Key IDThe confirmation page, or the file name
Team IDTop-right of the Apple Developer portal, or under Membership
Bundle IDYour Xcode project
EnvironmentSandbox for development builds, Production for App Store and TestFlight builds

For more information about this step, see Connect mobile apps in the marketing guide. 

Step 3: Integrate the Connect SDK

Follow the Integrate the Connect SDK into a native iOS app (Swift) guide. Using the app key and collector URL from your Connect administrator.

Step 4: Configure push notifications in the Apple Developer portal

Push notifications in Connect require three components working together:

ComponentPurpose
Main appInitializes the SDK with push configuration and requests notification permission from the user
Notification Service Extension (NSE)Downloads rich media (images) and records delivery, including dismissed notifications
Notification Content Extension (NCE)Renders the expanded notification view when the user long-presses a notification

All three targets share an App Group — a shared container that lets them exchange push data. The App Group identifier must be identical across all three targets and your SDK configuration. A mismatch in any one location causes delivery tracking and rich media to silently fail.

Register or update your App ID

If you are registering a new App ID:

  1. In your Apple Developer account, go to Identifiers > +.
  2. Select App IDs > App and click Continue.
  3. Enter a description and your bundle ID (for example, com.yourcompany.yourapp).
  4. Under Capabilities, enable Push Notifications and App Groups.
  5. Click Continue > Register.

If your App ID already exists:

  1. Click the App ID in the list to open it.
  2. Under Capabilities, enable Push Notifications and App Groups.
  3. Click Save.
📘

Note

If you use Automatically manage signing in Xcode, these changes should be picked up automatically. If the capabilities do not appear in Xcode after saving, go to Xcode > Settings > Apple Accounts, select your account and team and click Download Manual Profiles to force a refresh.

Register App IDs for the extensions

Repeat the App ID registration for each extension target, enabling App Groups only. Unlike the main app, extension App IDs do not require the Push Notifications capability.

  • com.yourcompany.yourapp.NotificationServiceExtension
  • com.yourcompany.yourapp.NotificationContentExtension

Create an App Group

  1. Go to Identifiers > + and select App Groups.
  2. Enter a description and an identifier using the group. prefix convention (for example, group.com.yourcompany.yourapp).
  3. Click Continue > Register.
  4. Go back to each of your three App IDs (main app, NSE, NCE) and assign the App Group you just created.
🚧

Warning

The App Group identifier is not the same as your bundle ID. It must start with group. and be identical across all targets and your SDK configuration. Even a single character mismatch will cause delivery tracking and rich media to silently fail.

Step 5: Configure push notifications in Xcode

Configure Info.plist

Add the following to your main app's Info.plist to enable background push delivery:

<key>UIBackgroundModes</key>
<array>
    <string>remote-notification</string>
</array>

Initialize the SDK with push configuration

Add the push configuration to your existing ConnectSDK.shared.enable() call:

push: ConnectPushConfig(
    mode: .automatic,
    appGroupIdentifier: "group.com.yourcompany.yourapp"
)
📘

Note

The SDK manages APNs token registration and notification callbacks automatically. Do not set your own UNUserNotificationCenter.delegate — doing so will prevent push signals from being tracked in Connect.

Add the Notification Service Extension

The NSE downloads rich media and records push delivery.

Create the extension target

  1. In Xcode, go to File > New > Target.
  2. Select Notification Service Extension and click Next.
  3. Name it NotificationServiceExtension and ensure Embed in Application shows your main app.
  4. Click Finish.
  5. If a confirmation message appears, select Activate. It can be useful for debugging.

Add the SDK dependency

In Xcode, select the NSE target, go to General > Frameworks and Libraries and add the Connect library.

Add Connect SDK to NotificationServiceExtension

Implement the extension

Replace the generated NotificationService.swift with the following. Use the same App Group identifier as your main app.

import Connect

final class NotificationService: ConnectNotificationService, @unchecked Sendable {
    override var appGroupIdentifier: String? {
        "group.com.yourcompany.yourapp"
    }
}
📘

Note

@unchecked Sendable is required when strict concurrency checking is enabled (Swift 6 or later, or when explicitly enabled in your build settings). You can omit it if your project does not use strict concurrency checking.

Verify the Info.plist

Xcode generates an Info.plist for the NSE target. Verify that NSExtensionPrincipalClass is set to $(PRODUCT_MODULE_NAME).NotificationService.

Info.plist for the NSE target

Add the Notification Content Extension

The NCE renders the expanded notification view when the user long-presses a notification.

Create the extension target

  1. In Xcode, go to File > New > Target.
  2. Select Notification Content Extension and click Next.
  3. Name it NotificationContentExtension, ensure Embed in Application shows your main app, and click Finish.
  4. If a confirmation message appears, click Activate.

Add the SDK dependency

In Xcode, select the NCE target, go to General > Frameworks and Libraries and add the Connect library.

Implement the extension

Replace the generated NotificationViewController.swift with the following. Use the same App Group identifier as your main app.

import Connect

final class NotificationViewController: ConnectNotificationContentExtension, @unchecked Sendable {
    override var appGroupIdentifier: String? {
        "group.com.yourcompany.yourapp"
    }
}

Configure the NCE Info.plist

Update the NCE's Info.plist to register for Acoustic notification categories:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSExtension</key>
    <dict>
        <key>NSExtensionAttributes</key>
        <dict>
            <key>UNNotificationExtensionCategory</key>
            <array>
                <string>ACOUSTIC_RICH_NOTIFICATION</string>
                <string>ACTIONABLE_NOTIFICATION</string>
            </array>
            <key>UNNotificationExtensionDefaultContentHidden</key>
            <false/>
            <key>UNNotificationExtensionInitialContentSizeRatio</key>
            <real>1</real>
        </dict>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.usernotifications.content</string>
        <key>NSExtensionPrincipalClass</key>
        <string>$(PRODUCT_MODULE_NAME).NotificationViewController</string>
    </dict>
</dict>
</plist>

Delete the storyboard

Xcode generates a MainInterface.storyboard for the NCE. Delete this file and remove the NSExtensionMainStoryboard key from the NCE's Info.plist if present. The SDK handles all UI programmatically.

Sample MainInterface.storyboard

Enable capabilities in Xcode

After enabling the capabilities on the App ID in step 4, you must also add them to the targets in Xcode. For each of your three targets (main app, NSE, NCE):

  1. Select the target in Xcode and go to Signing & Capabilities.
  2. Click + Capability > App Groups.
  3. Add the App Group identifier you created in Step 4.

For the main app target only, also add the Push Notifications capability.

Step 6: Request notification permission

Your app must request notification permission from the user. Add the following at an appropriate point in your app's UX — for example, after an onboarding screen that explains the value of notifications rather than on first launch.

func requestNotificationPermission() {
    UNUserNotificationCenter.current().requestAuthorization(
        options: [.alert, .badge, .sound]
    ) { granted, error in
        try? ConnectSDK.shared.push.didReceiveAuthorization(granted: granted, error: error)
    }
}
🚧

Warning

iOS only shows the system permission dialog once. If the user denies it, the only way to re-enable notifications is through the Settings app. Design your UX accordingly.

Testing

On the simulator

You can test basic push delivery in the simulator using .apns payload files. Drag an .apns file onto the running simulator to send a test notification.

A basic test payload:

{
    "Simulator Target Bundle": "com.yourcompany.yourapp",
    "aps": {
        "alert": {
            "title": "Test notification",
            "body": "This is a test push notification."
        },
        "sound": "default"
    }
}

To test rich push (images), add "mutable-content": 1 to the payload. This tells iOS to invoke the NSE before displaying the notification:

{
    "Simulator Target Bundle": "com.yourcompany.yourapp",
    "aps": {
        "alert": {
            "title": "Rich notification",
            "body": "This notification includes an image."
        },
        "mutable-content": 1,
        "sound": "default"
    },
    "data": {
        "notification": {
            "expandedImage": "https://example.com/image.jpg"
        }
    }
}

On a device

Full end-to-end testing requires a physical device. The simulator cannot receive real remote push notifications.

  1. Build and run on a physical device.
  2. Grant notification permission when prompted.
  3. Send a test push from the Acoustic Connect dashboard.
  4. Verify the notification appears, images load, and push signals appear in the dashboard.

Troubleshooting

Push token not received

Possible causes:

  • Running on the simulator — APNs tokens are not available on the simulator
  • The user denied notification permission
  • remote-notification is missing from UIBackgroundModes in Info.plist
  • The bundle ID in your Xcode project does not match the App ID with Push Notifications enabled in the Apple Developer portal

Rich push images not showing

Verify the following:

  • "mutable-content": 1 is present in the push payload
  • The NSE target includes the Connect library
  • The appGroupIdentifier in the NSE exactly matches the main app
  • The image URL is accessible over HTTPS and is not too large

Push signals not appearing in Acoustic Connect

Verify the following:

  • The appKey and collector URL in your ConnectConfig match the dashboard configuration
  • You are not setting your own UNUserNotificationCenter.delegate
  • The App Group identifier is consistent across all three targets and your ConnectPushConfig

Extension crashes on launch

Common causes:

  • The Connect library is not linked to the extension target
  • NSExtensionPrincipalClass in the extension's Info.plist is incorrect — it must be $(PRODUCT_MODULE_NAME).YourClassName
  • The App Group entitlement is missing on the extension target

Troubleshooting tip

To enable SDK debug logging, add these environment variables with a value of 1 to your scheme (Product > Scheme > Edit Scheme > Run > Arguments > Environment Variables):

  • CONNECT_DEBUG
  • TLF_DEBUG
  • EODebug

When reporting an issue to our support team, always attach your debug log. It speeds up troubleshooting.