For the complete documentation index, see llms.txt. This page is also available as Markdown.

Push Message Integration

Can be used alongside other push solutions

To use alongside another push solution, you must disable the Swizzling option of that solution.

After disabling Swizzling, refer to that solution's guide to manually configure push notification handling.

1

Configure APNs

To use Push Messages in an iOS app, you need to configure the integration between the Hackle Workspace and APNs.

For more details, see Apple Push Notification Service Configuration.

2

Add PushNotification Capability to the App

In the Xcode project settings, click + Capability in the Signing & Capabilities tab as shown below.

Add Push Notifications and Background Modes.

Then enable Remote notifications in Background Modes.

3

Configure AppDelegate

AppDelegate configuration is required to collect push tokens, display Push Messages, and handle push clicks.

AppDelegate is required for Push Message integration.

Complete the following configuration so Hackle can deliver Push Messages to devices with the iOS app installed.

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
  ) -> Bool {
    return true
  }
}

If using SwiftUI, register the AppDelegate with SwiftUI as follows.

import SwiftUI

@main
struct sampleApp: App {
  ...
  @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
  ...
}
4

Collect Push Token

Add the setPushToken method to AppDelegate as shown below.

import Hackle

class AppDelegate: NSObject, UIApplicationDelegate {
  ...
  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    // iOS 앱에서 푸시 권한 요청
    let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]

    UNUserNotificationCenter.current().requestAuthorization(
      options: authOptions,
      completionHandler: { _, _ in }
    )

    UNUserNotificationCenter.current().delegate = self
    application.registerForRemoteNotifications()

    // 핵클 SDK 초기화
    Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY)
    return true
  }

  func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
  ) {
    // 핵클 서버로 APNs 푸시 토큰 전달
    Hackle.app()?.setPushToken(deviceToken)
  }
  ...
}
5

Display Push Messages

In the background, pushes are displayed automatically without any code implementation.

Add the userNotificationCenter method to display foreground Push Messages.

import Hackle

extension AppDelegate: UNUserNotificationCenterDelegate {
  // Foreground push message
  func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    willPresent notification: UNNotification,
    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions
  ) -> Void) {

    if Hackle.userNotificationCenter(
      center: center, willPresent: notification, withCompletionHandler: completionHandler
    ) {
      // Succefully processed notification
      // Automatically consumed completion handler
      return
    } else {
      // Received not hackle notification or error
      print("Do something")

      if #available(iOS 14.0, *) {
        completionHandler([.list, .banner])
      } else {
        completionHandler([.alert])
      }
    }
  }
}

If the push was not sent by Hackle, false is returned.

6

Handle Push Click

Add the handleNotification method to handle push clicks.

import Hackle

extension AppDelegate: UNUserNotificationCenterDelegate {
  // push click
  public func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    didReceive response: UNNotificationResponse,
    withCompletionHandler completionHandler: @escaping () -> Void
  ) {

    if let _ = Hackle.handleNotification(response: response) {
      // process hackle notification
    } else {
      // not hackle notification or error
      print("do something")
    }

    // handleNotification 에서 completionHandler를 호출하지 않으니
    // 핵클 푸시 여부에 관계없이 반드시 completionHandler를 호출해야 합니다.
    completionHandler()
  }
}

The push click function processes in the following order:

  1. Check if the push was sent by Hackle

  2. Send the push click event to the Hackle server

  3. (If it is a deep link push) Handle the deep link

If the push was not sent by Hackle, nil is returned.

Custom Deep Link Handling for Push Click

If you need to reprocess the link received from Hackle within the app, declare the handleAction parameter as false when calling handleNotification.

When the handleAction parameter is false:

  • The Hackle SDK sends the push click event to the Hackle server.

  • Deep link handling is not performed.

The actionType for a Push Message is as follows.

actionType
Description

appOpen

Open the app

link

Open the app and navigate to a link

When actionType is appOpen, link is nil.

7

Test Push Messages

Check Token

Test

8

Push Message Reception

On iOS, whether a push is received depends on the build environment.

Even when the APNs Key Environment is set to Sandbox & Production, the range of Push Messages that can be received differs by Hackle environment and app build environment as follows.

Hackle Environment
APNs Environment
Build Environment

Development Environment, Development/Production Test Push

Sandbox

Direct run from Xcode, Development provisioning

Production Environment

Production

TestFlight, Ad Hoc, App Store distribution

Hackle Push Messages support deep link navigation on click.

When the app is opened via a Push Message, you can retrieve the opened deep link information using the following configuration.

For more details on iOS deep links, see the iOS Deep Link Guide.

If you have used Custom Deep Link Handling for Push Click, the deep link information is not passed as shown below.

import SwiftUI

@main
struct sampleApp: App {
  ...
  var body: some Scene {
    WindowGroup {
      ContentView()
        .onOpenURL(perform: { url in
          // Handle opened url
          print("\(url.absoluteString) opened.")
        })
    }
  }
  ...
}

Last updated