Skip to main content

Native iOS (Swift) Integration Guide

This guide walks you through integrating HoberKit into a native iOS application — from Swift Package Manager installation through foreground and background notification handling.

Minimum deployment target: iOS 16

For the full API surface, see the API Reference.


Prerequisites

  • Xcode 15 or later
  • An active Hober account with a valid SDK key and channel ID
  • An Apple Developer account with the Push Notifications capability enabled on your App ID
  • APNs credentials configured in the Hober dashboard (APNs Auth Key .p8 or APNs Certificate .p12)

Step 1 — Install via Swift Package Manager

Use Xcode's Package Dependencies UI to add HoberKit:

  1. Open your project in Xcode and select File > Add Package Dependencies…
  2. Enter the repository URL:
    https://github.com/hoberhq/hober-ios-sdk.git
  3. Choose Up to Next Major Version starting from 1.0.0.
  4. Select the HoberKit library target and click Add Package.

Alternatively, add it directly to Package.swift:

dependencies: [
.package(url: "https://github.com/hoberhq/hober-ios-sdk.git", from: "1.0.0"),
],
targets: [
.target(
name: "YourApp",
dependencies: ["HoberKit"]
),
]

Step 2 — Configure in AppDelegate

Call Hober.configure(sdkKey:channelId:) as early as possible — inside application(_:didFinishLaunchingWithOptions:):

import UIKit
import HoberKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
Hober.configure(sdkKey: "YOUR_SDK_KEY", channelId: "YOUR_CHANNEL_ID")
return true
}

// MARK: - APNs token registration

func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Hober.registerDevice(token: deviceToken)
}

func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
print("[Hober] Failed to register for remote notifications: \(error)")
}
}
Finding your credentials

Your sdkKey and channelId are available in the Hober dashboard under Settings > SDK Keys.


Step 3 — Request Notification Permission

Call Hober.requestPermission() at a meaningful moment in your onboarding flow — triggered by a user gesture such as tapping an "Enable Notifications" button. Avoid prompting immediately on launch; iOS only allows one system prompt per app install.

import HoberKit

class OnboardingViewController: UIViewController {

@IBAction func enableNotificationsTapped(_ sender: UIButton) {
Task {
let granted = await Hober.requestPermission()
if granted {
print("[Hober] Notification permission granted.")
} else {
print("[Hober] Notification permission denied.")
showPermissionDeniedHelp()
}
}
}

private func showPermissionDeniedHelp() {
// Direct users to Settings > Notifications > YourApp to re-enable
}
}

Hober.requestPermission() calls UNUserNotificationCenter.requestAuthorization internally and also registers with APNs via UIApplication.registerForRemoteNotifications().


Step 4 — Identify a Subscriber

After the user logs in or completes sign-in, associate them with a Hober subscriber record:

import HoberKit

// Call this after the user has been authenticated
func onUserLoggedIn(user: User) {
Task {
try await Hober.identifySubscriber(
externalId: user.id,
email: user.email,
attributes: ["plan": user.plan, "locale": user.locale]
)
}
}
ParameterTypeRequiredDescription
externalIdStringYesYour internal user ID
emailString?NoUser email for segmentation
attributes[String: String]?NoCustom key-value attributes

Call Hober.identifySubscriber again whenever the subscriber's data changes (e.g. plan upgrade).


Step 5 — Register the APNs Device Token

When iOS delivers the APNs device token, forward it to Hober. Add this to your AppDelegate (already shown in the boilerplate above):

func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Hober.registerDevice(token: deviceToken)
}

Hober.registerDevice(token:) converts the raw Data token to a hex string and registers it with the Hober backend so your app can receive targeted push notifications.


Step 6 — Handle Foreground Notifications

By default, iOS suppresses notification banners when the app is in the foreground. Implement UNUserNotificationCenterDelegate to display them:

import UserNotifications
import HoberKit

extension AppDelegate: UNUserNotificationCenterDelegate {

// Called when a notification arrives while the app is in the foreground
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
// Show banner, sound, and badge even in the foreground
completionHandler([.banner, .sound, .badge])
}

// Called when the user taps the notification
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
Hober.handleNotificationResponse(userInfo: userInfo)
completionHandler()
}
}

Set the delegate early in application(_:didFinishLaunchingWithOptions:):

UNUserNotificationCenter.current().delegate = self

Step 7 — Handle Background (Silent) Notifications

Silent pushes use the content-available flag to wake your app in the background. Enable the Background Modes > Remote notifications capability in Xcode, then handle the payload:

// In AppDelegate
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
// content-available: 1 signals a silent push
Hober.handleSilentNotification(userInfo: userInfo)
completionHandler(.newData)
}
Background fetch budget

iOS grants your app approximately 30 seconds to complete background processing. Keep the handler fast and always call completionHandler.


Complete AppDelegate Boilerplate

Copy-paste this as a starting point and fill in your credentials:

import UIKit
import UserNotifications
import HoberKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// 1. Configure HoberKit
Hober.configure(sdkKey: "YOUR_SDK_KEY", channelId: "YOUR_CHANNEL_ID")

// 2. Set notification center delegate for foreground handling
UNUserNotificationCenter.current().delegate = self

return true
}

// MARK: - APNs Token Registration

func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Hober.registerDevice(token: deviceToken)
}

func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
print("[Hober] Registration failed: \(error)")
}

// MARK: - Background / Silent Notifications

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

// MARK: - UNUserNotificationCenterDelegate

extension AppDelegate: UNUserNotificationCenterDelegate {

func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
completionHandler([.banner, .sound, .badge])
}

func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
Hober.handleNotificationResponse(userInfo: response.notification.request.content.userInfo)
completionHandler()
}
}

Troubleshooting

APNs Auth Key vs APNs Certificate

Hober supports two authentication methods for APNs:

MethodFileExpiresRecommended
APNs Auth Key.p8NeverYes
APNs Certificate.p12AnnuallyLegacy only

Recommendation: Use an APNs Auth Key (.p8) from the Apple Developer portal — it never expires and works across all your apps under the same Team ID. Upload it in the Hober dashboard under Settings > APNs Credentials.

Sandbox vs Production

APNs has two environments:

  • Sandbox — used automatically when the app is built and run via Xcode (development provisioning profile).
  • Production — used when the app is distributed via TestFlight or the App Store.

Hober detects the environment from the APNs token automatically. Ensure that your APNs Auth Key or Certificate is configured for the correct environment in the Hober dashboard. Sending a sandbox token to the production APNs endpoint (or vice versa) will silently drop the notification.

Entitlements Checklist

Verify the following in your Xcode project:

  • Push Notifications capability is enabled under Signing & Capabilities.
  • The entitlement aps-environment is set to development (debug) or production (release) in your .entitlements file.
  • Background Modes capability is enabled and Remote notifications is checked (required for silent pushes).
  • Your provisioning profile includes the Push Notifications entitlement — regenerate it if you added the capability after the profile was created.

Notifications Not Arriving in Simulator

APNs push delivery to the iOS Simulator is supported from Xcode 11.4+ using .apns payload files dragged onto the simulator window. However, the Simulator cannot receive live APNs payloads from your server. Test real push delivery on a physical device.

Permission Prompt Not Appearing

If the system permission alert does not appear after calling Hober.requestPermission():

  • The user may have already responded to the prompt. iOS only shows the alert once.
  • Check current authorization status: UNUserNotificationCenter.current().getNotificationSettings { ... }.
  • Direct the user to Settings > Notifications > YourApp to re-enable notifications manually.