iOS SDK integration
Add BNotify with Swift Package Manager, enable Push Notifications, drop in bnotify-config.plist, and wire AppDelegate. Optionally add a Notification Service Extension for delivery tracking and rich images.
Before SPM setup, create a project, add an iOS app, and download bnotify-config.plist. Then continue below.
What you get after integration
| Capability | How it works |
|---|---|
| Permission prompt | SDK requests alert, sound, and badge |
| Device token | Forward the system token to the SDK at launch |
| Click / dismiss / action | Call trackEvent from the notification response |
Delivery (received) | Optional Notification Service Extension |
| In-app messages | Modal, card, banner, fullscreen, and image |
| Default category | bnotify with action OPEN |
The iOS SDK does not send notifications. Register the device, then create and send campaigns from the BNotify dashboard. Upload your Apple Push credentials in the dashboard so iOS devices can receive them.
Prerequisites
| Requirement | Notes |
|---|---|
| Xcode 15+ | SPM + Swift package |
| Deployment Target ≥ 13.0 | Matches SDK |
| Apple Developer Program | Required for real-device push |
| Push Notifications capability | App ID + profiles |
| Physical device | Required for real push testing |
| Dashboard plist | Download bnotify-config.plist after you register the iOS app in Console |
Integration checklist
- 1Add SPM product
BNotifyto the app target - 2Enable Push Notifications capability
- 3Add
bnotify-config.plistto the app target - 4Wire register APIs at launch
- 5Forward the device token / registration error to the SDK
- 6Implement click/dismiss
trackEvent - 7App Groups + Notification Service Extension
- 8Disable verbose logs in Release
Step 1 — Add the Swift Package
- Xcode → File → Add Package Dependencies…
- Enter:
https://gitlab.com/hamza.hafeez/bnotifyiossdk.git - Choose version rule (e.g. Up to Next Major).
- Add product BNotify to the main app (and NSE if you create one).
import BNotify
Step 2 — Apple Developer / Xcode capabilities
- Apple Developer → Identifiers → enable Push Notifications on your App ID.
- Renew provisioning profiles that include Push.
- Upload your Apple Push key (
.p8) or certificates in the BNotify dashboard. - In Xcode target → Signing & Capabilities → + Capability → Push Notifications.
For NSE delivery tracking, add the same App Group on the app and extension targets, then set appGroupId in the plist.
Step 3 — Add bnotify-config.plist
Download from the BNotify Console after you register the iOS app (see Create a project). Keep the filename exactly bnotify-config.plist and include it in the main app target membership. The SDK loads it from Bundle.main.
<?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>projectId</key>
<string>your-project-id</string>
<key>packageName</key>
<string>com.example.yourapp</string>
<key>apiKey</key>
<string>your-api-key</string>
<key>appId</key>
<string>your-app-id</string>
<key>authDomain</key><string></string>
<key>databaseURL</key><string></string>
<key>storageBucket</key><string></string>
<key>messagingSenderId</key><string></string>
<key>measurementId</key><string></string>
</dict>
</plist>
The dashboard download is enough. Do not add extra URL keys to the plist.
Step 4 — Wire AppDelegate
import UIKit
import UserNotifications
import BNotify
@main
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
UNUserNotificationCenter.current().delegate = self
#if !DEBUG
BNotifyLog.isEnabled = false
#endif
BNotifyManager.shared.registerCategories()
BNotifyManager.shared.registerForPushNotifications()
return true
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
BNotifyManager.shared.didRegisterForRemoteNotifications(token: deviceToken)
}
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
BNotifyManager.shared.didFailToRegisterForRemoteNotifications(error: error)
}
}
Keep device-token callbacks on AppDelegate even when using SceneDelegate.
Step 5 — Track clicks, dismissals & actions
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
let type: String
let actionId: String
switch response.actionIdentifier {
case UNNotificationDismissActionIdentifier:
type = "dismissed"; actionId = "dismiss"
case UNNotificationDefaultActionIdentifier:
type = "clicked"; actionId = "clicked"
default:
type = "action"; actionId = response.actionIdentifier
}
BNotifyManager.shared.trackEvent(type: type, userInfo: userInfo, actionId: actionId)
// Optional: navigate from userInfo
completionHandler()
}
| User action | Suggested type | Suggested actionId |
|---|---|---|
| Tap body | clicked | clicked |
| Dismiss | dismissed | dismiss |
| Tap Open | action | OPEN |
Step 6 — Foreground display (optional)
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
if #available(iOS 14.0, *) {
completionHandler([.banner, .sound, .badge])
} else {
completionHandler([.alert, .sound, .badge])
}
}
Step 7 — Notification Service Extension (recommended)
Use an NSE to report received and attach images for collapsed thumbnail + expanded media (GIF animates natively).
- File → New → Target → Notification Service Extension.
- Link product BNotify to the extension.
- Enable the same App Group on app + extension; set
appGroupIdin plist.
import UserNotifications
import BNotify
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
BNotifyExtensionSafe.prepareNotificationContent(request) { content in
contentHandler(content)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler, let bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
In-app messages
In-app campaigns appear inside the app (modal, card, top banner, fullscreen, and image). They are separate from lock-screen notifications. Optional custom triggers:
BNotifyInApp.start() // optional; also starts from config load
BNotifyInApp.logEvent("purchase_completed")
Rich media payload
For NSE + rich media, include mutable-content: 1 and put imageUrl as a sibling of aps:
{
"aps": {
"alert": { "title": "Hello", "body": "World" },
"sound": "default",
"mutable-content": 1,
"category": "bnotify"
},
"notificationId": "n-123",
"token": "<device-or-tracking-token>",
"imageUrl": "https://cdn.example.com/promo.gif",
"isExpanded": true
}
If mutable-content is missing, the NSE may not run — no received tracking and no expanded image attachment.
Verification
- Run on a physical device with Push capability.
- Grant notification permission; confirm the device appears in the BNotify dashboard.
- Send a test push from the BNotify dashboard with
notificationIdand categorybnotify. - Tap / dismiss → events appear in analytics.
- With NSE: confirm
received+ image thumbnail / expand.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| No token / registration fails | Push capability or provisioning | Enable Push on App ID; use real device |
| Text-only push, no image | Missing NSE / mutable-content / imageUrl | Add NSE; put imageUrl outside aps |
| App not found on register | Wrong appId / bundle | Match dashboard app + packageName |
| No dismiss events | Category not bnotify | Call registerCategories(); set category in payload |
| In-app never shows | Offline or incomplete init | Confirm config load, network, and that registerForPushNotifications() ran |
See the FAQ or contact support at bnotify93@gmail.com.