Skip to main content

iOS Quickstart

This guide walks you through integrating PushEngage push notifications into a native iOS application. Estimated time: 15 minutes.

After completing this guide, your app will receive push notifications with rich media support. See the iOS SDK Reference for the full API.

Migration Guide: 0.1.0 → 1.0.0

The SDK is now split into two modules so notification extension targets no longer link app-only code (this fixes a CocoaPods regression that broke push delivery on production builds).

  • PushEngage — link to your app target only. App-target code is unchanged.
  • PushEngageExtension — link to your Notification Service / Content Extension target(s).

For existing 0.1.0 integrations, three things change in each extension target:

  1. Dependency

    • CocoaPods: pod 'PushEngage'pod 'PushEngageExtension'
    • SPM: link the PushEngageExtension product instead of PushEngage
  2. Import: import PushEngageimport PushEngageExtension (Objective-C: @import PushEngage;@import PushEngageExtension;)

  3. Call sites: replace the PushEngage class prefix with PushEngageExtension — method names are unchanged.

    // Before
    PushEngage.didReceiveNotificationExtensionRequest(request, bestContentHandler: bestContent)
    PushEngage.serviceExtensionTimeWillExpire(request, content: bestAttemptContent)
    PushEngage.getCustomUIPayLoad(for: notification.request)

    // After
    PushEngageExtension.didReceiveNotificationExtensionRequest(request, bestContentHandler: bestContent)
    PushEngageExtension.serviceExtensionTimeWillExpire(request, content: bestAttemptContent)
    PushEngageExtension.getCustomUIPayLoad(for: notification.request)

You can also remove the APPLICATION_EXTENSION_API_ONLY = 'NO' Podfile post_install build-setting override from earlier versions — it is no longer needed.

Objective-C with modules disabled: if an app target builds with CLANG_ENABLE_MODULES = NO (or uses Objective-C++), also add #import <PushEngageExtension/PushEngageExtension-Swift.h> where you use the notification model types (PENotification, PENotificationOpenResult, SubscriberDetailsData). Targets with modules enabled (the default) need nothing extra.

Prerequisites

  • Xcode installed
  • Apple Developer account with a valid App ID configured on the Apple Developer Portal
  • APNs certificate (.p12) (create one)
  • PushEngage account and App ID (see Get Your App ID)

Step 1 — Install the SDK

Choose either Swift Package Manager or CocoaPods. Use only one method.

  1. In Xcode, go to File → Add Package Dependencies.
  2. Paste https://github.com/awesomemotive/pushengage-ios-sdk into the search bar.
  3. Click Add Package.
  4. Under Add to Target, select your main app target.
  5. Click Add Package.

Step 2 — Configure Xcode Capabilities

Enable Push Notifications

  1. In Xcode, select the root project in the Project Navigator and choose your main app target.
  2. Go to Signing & Capabilities.
  3. Click + Capability and add Push Notifications.

If Push Notifications is not visible in Xcode: go to your Apple Developer account → Certificates, Identifiers & Profiles → select your App ID → enable Push Notifications → return to Xcode and try again.

Enable Background Modes

  1. Click + Capability and add Background Modes.
  2. Check both Remote notifications and Background fetch.

Step 3 — Connect to PushEngage Dashboard

  1. Log in to your PushEngage Dashboard.
  2. Navigate to Site Settings → Installation → iOS SDK.

Under "1. Configure your Apple iOS APNs settings":

  1. Enter your App Push Id (your iOS Bundle Identifier, e.g. com.example.MyApp).
  2. Upload your APNs Certificate (.p12).
  3. Enter the Private Key Password you set when exporting the .p12.
  4. Click Update.

Under "2. Install the SDK":

  1. Click Copy next to the App ID — you'll pass it to setAppID in the next step.

Step 4 — Initialize the SDK

Add PushEngage initialization to your AppDelegate:

AppDelegate.swift
import UIKit
import PushEngage

class AppDelegate: UIResponder, UIApplicationDelegate {

override init() {
super.init()
PushEngage.swizzleInjection(isEnabled: true)
}

func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
PushEngage.setAppID(id: "YOUR_APP_ID")
PushEngage.setInitialInfo(for: application, with: launchOptions)
PushEngage.enableLogging = true

// Prompt for notification permission. On grant, the SDK registers with
// APNs and subscribes the device automatically. Without this call the
// system prompt never appears and no subscriber is created.
PushEngage.requestNotificationPermission { granted, error in
print("Notification permission granted: \(granted)")
}
return true
}
}
note

Replace YOUR_APP_ID with the App ID copied in Step 3.

Production builds

Remove or set PushEngage.enableLogging = false before releasing to production. Leaving it enabled exposes internal SDK data in production app logs.

Step 5 — Send a Test Notification

  1. Build and run your app on a physical iOS device — push notifications do not work in the simulator.
  2. Accept the notification permission prompt when it appears.
  3. In the PushEngage Dashboard, go to Campaign → Push Broadcasts → Create New Push Broadcast.
  4. Send a test notification to yourself.

You should receive the notification within a few seconds. Your integration is complete. To unlock rich notifications and images, continue with the steps below.

Enable Rich Notifications

The following steps enable rich notifications (images, action buttons) and app badge sync. They require adding iOS extension targets to your Xcode project.

Step 6 — Add Notification Service Extension

The Notification Service Extension enables rich notifications (images, action buttons). It is required for full PushEngage functionality.

Create the Extension

  1. In Xcode, go to File → New → Target.
  2. Select Notification Service Extension and click Next.
  3. Name it PushEngageNotificationServiceExtension and click Finish.
  4. When prompted to activate the scheme, click Cancel — this keeps Xcode's debugging focus on your main app.
  5. Select the new extension target in the Project Navigator and set its Deployment Target to iOS 12 or above.

Add SDK Dependency to the Extension

Extension-only module

Notification extensions link the companion PushEngageExtension module, not the main PushEngage module. PushEngageExtension is extension-safe and ships the three notification-extension APIs (didReceiveNotificationExtensionRequest, serviceExtensionTimeWillExpire, getCustomUIPayLoad). Linking the wrong module will break push delivery on production builds.

  1. Select your project in the navigator.
  2. Select the PushEngageNotificationServiceExtension target.
  3. Go to General → Frameworks, Libraries, and Embedded Content.
  4. Click +, find PushEngageExtension, and add it.

Implement the Extension

Replace the auto-generated NotificationService.swift with:

PushEngageNotificationServiceExtension/NotificationService.swift
import UserNotifications
import PushEngageExtension

@available(iOSApplicationExtension 12.0, *)
class NotificationService: UNNotificationServiceExtension {

var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
var request: UNNotificationRequest?

override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
self.request = request
self.contentHandler = contentHandler
self.bestAttemptContent = request.content.mutableCopy() as? UNMutableNotificationContent

if let bestContent = bestAttemptContent {
PushEngageExtension.didReceiveNotificationExtensionRequest(request, bestContentHandler: bestContent)
contentHandler(bestContent)
}
}

override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler,
let request = request,
let bestAttemptContent = bestAttemptContent {
guard let content = PushEngageExtension.serviceExtensionTimeWillExpire(
request, content: bestAttemptContent
) else {
contentHandler(bestAttemptContent)
return
}
contentHandler(content)
}
}
}

Step 7 — Add Notification Content Extension (Optional)

The Notification Content Extension renders the custom expanded UI for PushEngage notifications sent with a matching category. Without it, notifications still deliver normally, but any custom expanded layout falls back to iOS's default view.

Create the Extension

  1. In Xcode, go to File → New → Target.
  2. Select Notification Content Extension and click Next.
  3. Name it PushEngageNotificationContentExtension and click Finish.
  4. When prompted to activate the scheme, click Cancel.
  5. Set the Deployment Target to iOS 12 or above.
  6. Open the extension's Info.plist. Under NSExtension → NSExtensionAttributes → UNNotificationExtensionCategory, set the array to contain the category identifier(s) you'll send with custom-UI notifications (must match the categoryIdentifier check in your extension code).

Add SDK Dependency

  1. Select your project in the navigator.
  2. Select the PushEngageNotificationContentExtension target.
  3. Go to General → Frameworks, Libraries, and Embedded Content.
  4. Click +, find PushEngageExtension, and add it.

Implement the Extension

PushEngageNotificationContentExtension/NotificationViewController.swift
import UIKit
import UserNotifications
import UserNotificationsUI
import PushEngageExtension

@available(iOSApplicationExtension 12.0, *)
class NotificationViewController: UIViewController, UNNotificationContentExtension {

override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
}

func didReceive(_ notification: UNNotification) {
if notification.request.content.categoryIdentifier == "your_category_identifier" {
let payload = PushEngageExtension.getCustomUIPayLoad(for: notification.request)
// Pass payload to your custom SwiftUI or UIKit view
}
}
}

Step 8 — Add App Groups

App Groups enable communication between the main app and notification extensions. This step is required.

  1. Select your main app target in Xcode → Signing & Capabilities+ CapabilityApp Groups.
  2. Click + to add a new App Group with a unique name, e.g., group.com.yourcompany.yourapp.
  3. In your main app target's Info.plist, add:
    • Key: PushEngage_App_Group_Key
    • Value: group.com.yourcompany.yourapp
  4. In PushEngageNotificationServiceExtension's Info.plist, add the same key and value.
  5. Select the extension target → Signing & Capabilities → enable the same App Group.

Troubleshooting

Build error: User Script Sandboxing
In Xcode → Build Settings → search for User Script Sandboxing → set to No.

Conflict between Firebase SDK and PushEngage swizzling
Disable PushEngage swizzling and wire up all four delegate methods below — omitting any one will silently break notifications, click tracking, or foreground display:

// In AppDelegate.init()
PushEngage.swizzleInjection(isEnabled: false)

// In AppDelegate
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
PushEngage.registerDeviceToServer(with: deviceToken)
}

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

// Set yourself as UNUserNotificationCenter delegate, then:
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler:
@escaping (UNNotificationPresentationOptions) -> Void) {
PushEngage.willPresentNotification(center: center,
notification: notification,
completionHandler: completionHandler)
}

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

Next Steps