Skip to main content
SDKsiOS

Push notifications

APNs device token, push subscriptions, listeners, click tracking, and delivered notifications on iOS.

This document describes behavior implemented by the MotiSig SDK. Your app still needs the usual Xcode capabilities (Push Notifications, background modes if required) and provisioning with APNs.

What initialize installs

On the main queue, the SDK installs notification-center observation and AppDelegate method swizzling so it can receive the APNs device token and intercept notification delivery. It also starts permission monitoring and may request notification permission and register for remote notifications (unless disabled for tests).

See the MotiSig.initialize documentation in the SDK source for the exact statement of installed behavior.

Device token and push subscription

When an APNs device token arrives, it is stored. If a user id is already set, the SDK upserts a push subscription (POST …/push-subscriptions) with devicePlatform: ios, pushType: apns, the token, the current notification permission (granted / declined / unknown from UNAuthorizationStatus), and the customer enabled flag (see below). If setUser completes after the token exists, the SDK performs the same upsert at that point. If the token string changes, the SDK removes the old subscription then upserts the new one.

setNotificationEnabled(_:)

This is the customer-controlled server flag for whether this device’s subscription is enabled. It is persisted locally (survives logout()). Call it when your app UI lets the user turn MotiSig-delivered pushes on or off for this device; the SDK sends PATCH …/push-subscriptions with enabled. It does not change OS notification permission.

Permission vs enabled

When the user changes notification authorization in Settings and returns to the app, the SDK patches the push subscription permission field only (it does not infer enabled from permission). notDetermined maps to unknown until the user responds to the prompt.

Notification listeners

Register a listener that conforms to MotiSigNotificationListener:

let subscription = MotiSig.shared.addNotificationListener(self, order: 0)
// later:
subscription.remove()

Behavior:

  • Listeners are held weakly. Retain your listener object for as long as you need callbacks.
  • order controls sort priority: lower values are notified first. nil behaves like 0. For the same order, registration order (FIFO) applies.
  • Callbacks are delivered on the main queue via motiSig(didReceiveNotification:inForeground:).
  • If no listeners are registered when an event arrives, the SDK buffers a bounded set of events; when you add a listener, buffered events are replayed on the main queue before new live events.
  • MotiSigNotificationSubscription.remove() is idempotent and safe from any thread. Dropping the subscription object without calling remove() does not unregister the listener.
  • logout() and removeAllNotificationListeners() clear listeners and the buffer.

MotiSigNotification

Contains optional messageId, title, body, and userInfo (string-keyed copy of the APNs payload). When the event originates from UserNotifications (delegate delivery or fetchDeliveredNotifications), requestIdentifier is set to UNNotificationRequest.identifier when non-empty; synthetic or test payloads may leave it nil.

Fetching delivered notifications (explicit)

MotiSig.shared.fetchDeliveredNotifications() returns [MotiSigDeliveredNotification], each with requestIdentifier, date (system delivery time), and notification (MotiSigNotification) for every entry still present in the system Notification Center (UNUserNotificationCenter.getDeliveredNotifications).

Call this when your app wants to reconcile in-app state with the OS list—for example on scenePhase == .active or UIApplication.didBecomeActiveNotification—so pushes that arrived while the app was backgrounded appear even if the user opened the app from the home screen without tapping the notification.

This is not strictly “only while inactive”: the delivered list can overlap with listener callbacks (foreground willPresent or tap) until the user dismisses notifications from Notification Center. Deduplicate using requestIdentifier (and/or messageId) against rows you already recorded from MotiSigNotificationListener.

On watchOS the method returns an empty array.

Click tracking

When the user acts on a notification (for example taps it) and the notification center delivers didReceive response, the SDK calls the delivery path with click tracking enabled. In that case, if a messageId can be extracted from the payload and a user is set, the SDK sends a track-click request. If messageId is missing or no user is set, tracking is skipped (see SDK logs at .debug).

For notifications presented in the foreground (willPresent), the SDK delivers the event to listeners but does not run click tracking on that path.

Foreground vs background app state is passed through for the track-click request payload where applicable.

Rich notification images (Notification Service Extension)

Apple does not download remote image URLs for you. To show an image in the banner, the push needs mutable-content: 1 and your app needs a Notification Service Extension that calls MotiSigRichPushHandler.handle(...).

Full setup (Xcode steps, payload contract, foreground gotchas, troubleshooting): see Rich notification images.