Troubleshoot Multiple Push SDKs with Swizzling Enabled

If Swizzling is enabled, implement the other push provider’s delegate methods first. When that’s complete, implement the Salesforce Engagement SDK methods.

  1. Configure the SDK along with the other Push provider, as shown in these code examples.

    Code example for iOS SDK v10 or later:
    1func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    2    if let options = launchOptions, let notification = options[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] {
    3        self.notificationUserInfo = notification
    4    }
    5
    6    FirebaseApp.configure()
    7    Messaging.messaging().delegate = self
    8    self.configureSdk()
    9
    10    if #available(iOS 10.0, *) {
    11        UNUserNotificationCenter.current().delegate = self
    12
    13        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
    14        UNUserNotificationCenter.current().requestAuthorization(
    15            options: authOptions,
    16            completionHandler: { _, _ in }
    17        )
    18    } else {
    19        let settings: UIUserNotificationSettings =
    20        UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
    21        application.registerUserNotificationSettings(settings)
    22    }
    23    application.registerForRemoteNotifications()
    24
    25    return true
    26
    27}
    28
    29@discardableResult
    30func configureSdk() -> Bool {
    31let appID = "<your appID here>"
    32let accessToken = "<your accessToken here>"
    33let appEndpointURL = "<your appEndpoint here>"
    34let mid = "<your account MID here>"
    35
    36#if DEBUG
    37SFMCSdk.setLogger(logLevel: .debug)
    38#endif
    39
    40    let appEndpoint = URL(string: appEndpointURL)!
    41
    42    var configBuilder = ConfigBuilder()
    43
    44    let engagementConfiguration = MarketingCloudSdkConfigBuilder(appId: appID)
    45        .setAccessToken(accessToken)
    46        .setMarketingCloudServerUrl(URL(string: appEndpointURL)!)
    47        .setMid(mid)
    48        .setInboxEnabled(true)
    49        .setLocationEnabled(true)
    50        .setAnalyticsEnabled(true)
    51        .build()
    52
    53    configBuilder = configBuilder
    54        .setEngagement(config: engagementConfiguration)
    55
    56    let pushFeatureConfiguration = PushFeatureConfigBuilder()
    57        .setApplicationControlsBadging(true)
    58        .build()
    59
    60    configBuilder = configBuilder
    61        .setPushFeature(config: pushFeatureConfiguration)
    62
    63    // Set the completion handler to take action when all modules initialization is completed.
    64    // Seting the completion handler is optional.
    65
    66    let completionHandler: ((_ status: [ModuleInitStatus]) -> Void) = { [weak self] status in
    67        DispatchQueue.main.async {
    68            self?.handleSDKInitializationCompletion(status: status)
    69        }
    70    }
    71
    72    SFMCSdk.initializeSdk(configBuilder.build(), completion: completionHandler)
    73
    74    return true
    75
    76}
    77
    78// MARK: - SDK Initialization Completion Handler
    79
    80private func handleSDKInitializationCompletion(status: [ModuleInitStatus]) {
    81var allSuccessful = true
    82
    83    for moduleStatus in status {
    84        print("Module: \(moduleStatus.moduleName.rawValue), Status: \(moduleStatus.initStatus.rawValue)")
    85
    86        if moduleStatus.initStatus == .success {
    87            // Handle successful initialization for each module
    88            switch moduleStatus.moduleName {
    89            case .engagement:
    90                // Handle successful initialization for Marketing cloud module
    91            case .pushFeature:
    92                // Handle successful initialization for Push Feature module
    93            default:
    94                break
    95            }
    96        } else if moduleStatus.initStatus == .error {
    97            allSuccessful = false
    98            // module failed to initialize, check logs for more details
    99        } else if moduleStatus.initStatus == .cancelled {
    100            allSuccessful = false
    101            // module initialization was cancelled (for example due to re-confirguration triggered before init was completed)
    102        } else if moduleStatus.initStatus == .timeout {
    103            allSuccessful = false
    104            // module failed to initialize due to timeout, check logs for more details
    105        }
    106    }
    107    if allSuccessful {
    108        print("SDK initialization completed successfully")
    109    } else {
    110        print("SDK initialization completed with errors - check logs above")
    111    }
    112
    113}
    Code example for iOS SDK v8:
    1func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    2    if let options = launchOptions, let notification = options[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] {
    3        self.notificationUserInfo = notification
    4    }
    5
    6    FirebaseApp.configure()
    7    Messaging.messaging().delegate = self
    8    self.configureSFMCSdk()
    9
    10    if #available(iOS 10.0, *) {
    11        UNUserNotificationCenter.current().delegate = self
    12
    13        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
    14        UNUserNotificationCenter.current().requestAuthorization(
    15            options: authOptions,
    16            completionHandler: { _, _ in }
    17        )
    18    } else {
    19        let settings: UIUserNotificationSettings =
    20        UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
    21        application.registerUserNotificationSettings(settings)
    22    }
    23    application.registerForRemoteNotifications()
    24
    25    return true
    26}
    27
    28@discardableResult
    29func configureSFMCSdk() -> Bool {
    30    let appID = "<your appID here>"
    31    let accessToken = "<your accessToken here>"
    32    let appEndpointURL = "<your appEndpoint here>"
    33    let mid = "<your account MID here>"
    34
    35#if DEBUG
    36    SFMCSdk.setLogger(logLevel: .debug)
    37#endif
    38
    39    let appEndpoint = URL(string: appEndpointURL)!
    40
    41    let mobilePushConfiguration = PushConfigBuilder(appId: appID)
    42        .setAccessToken(accessToken)
    43        .setMarketingCloudServerUrl(appEndpoint)
    44        .setMid(mid)
    45        .setInboxEnabled(true) // enable if needed by your application
    46        .setLocationEnabled(true) // enable if needed by your application
    47        .setAnalyticsEnabled(true) // enable if needed by your application
    48        .build()
    49
    50    let completionHandler: (OperationResult) -> () = { result in
    51        if result == .success {
    52            self.setupMobilePush()
    53        } else if result == .error {
    54        } else if result == .cancelled {
    55        } else if result == .timeout {
    56        }
    57    }
    58
    59    SFMCSdk.initializeSdk(ConfigBuilder().setPush(config: mobilePushConfiguration, onCompletion: completionHandler).build())
    60
    61    return true
  2. Configure the SDK to set the device token, as shown in these code examples.

    Code example for iOS SDK v10 or later:
    1// MARK: FireBaseMessaging Delegate
    2/**
    3Set deviceToken to MarketingCloudSDK in the FCM delegate method when Swizzling is enabled.
    4DeviceToken must be set MANDATORILY to MarketingCloudSDK using`SFMCSdk.mp.setDeviceToken` API for Push notifications to be received through Mobile Push.
    5*/
    6extension AppDelegate : MessagingDelegate {
    7    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    8        print("FCM Token", fcmToken ?? "")
    9
    10        PushFeature.requestSdk { pushFeature in
    11            print("SDK is operational")
    12            if let apnsToken = messaging.apnsToken {
    13                print("Setting APNs token in MarketingCloudSDK")
    14                pushFeature?.setDeviceToken(apnsToken)
    15            } else {
    16                print("fcm token is null")
    17            }
    18            print("SDK is not yet operational")
    19        }
    20    }
    21}
    Code example for iOS SDK v8:
    1// MARK: FireBaseMessaging Delegate
    2/**
    3Set deviceToken to MarketingCloudSDK in the FCM delegate method when Swizzling is enabled.
    4DeviceToken must be set MANDATORILY to MarketingCloudSDK using`SFMCSdk.mp.setDeviceToken` API for Push notifications to be received through Mobile Push.
    5*/
    6extension AppDelegate : MessagingDelegate {
    7    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    8        print("FCM Token", fcmToken ?? "")
    9
    10        SFMCSdk.requestPushSdk { mp in
    11            print("SDK is operational")
    12            if let apnsToken = messaging.apnsToken {
    13                print("Setting APNs token in MarketingCloudSDK")
    14                mp.setDeviceToken(apnsToken)
    15            } else {
    16                print("fcm token is null")
    17            }
    18            print("SDK is not yet operational")
    19        }
    20    }
    21
    22}
    ```

When Swizzling is enabled in the other push provider, respective delegate methods are intercepted. For example, when a push notification is received from Firebase, the payload received in the didReceive notification method for the UNUserNotificationCenterDelegate is altered to receive a MessagingMessageInfo object. Because the payload doesn’t match the format that the SDK expects, the message isn’t reported.

To handle this situation, implement the delegate methods described in these code examples.

Code example for iOS SDK v10 or later:
1```swift
2/* REQUIRED IMPLEMENTATION */
3func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
4    PushFeature.requestSdk { pushFeature in
5        pushFeature?.setNotificationUserInfo(userInfo)
6    }
7    completionHandler(.newData)
8}
9
10func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
11    PushFeature.requestSdk { pushFeature in
12        pushFeature?.setNotificationResponse(response)
13    }
14    completionHandler()
15}
16
17func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
18    completionHandler([.banner, .list, .sound])
19}
20```
Code example for iOS SDK v8:
1```swift
2    /* REQUIRED IMPLEMENTATION */
3    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
4        SFMCSdk.requestPushSdk { mp in
5            mp.setNotificationUserInfo(userInfo)
6        }
7        completionHandler(.newData)
8    }
9
10    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
11        SFMCSdk.requestPushSdk { mp in
12            mp.setNotificationRequest(response.notification.request)
13        }
14        completionHandler()
15    }
16
17    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
18        completionHandler([.banner, .list, .sound])
19    }
20```

Notification messages from other providers appear in the device’s notification center. However, any action on the notification message from the SDK, such as URL handling or reporting, doesn’t work.

See Also