2.x -> 2.2

Updated

Version 2.2 of the Customer.io Flutter SDK introduces a new CioAppDelegateWrapper pattern for iOS that simplifies push notification setup and eliminates the need for method swizzling.

Key Changes

The primary change in version 2.2 is the introduction of the wrapper pattern for handling push notifications on iOS. This change:

  • Eliminates method swizzling: No more automatic method replacement
  • Simplifies setup: Less boilerplate code required
  • Improves reliability: More predictable behavior

See the instructions below to update your Flutter app’s iOS configuration.

Upgrading to SDK 2.2

Update your dependencies:

  1. Update your pubspec.yaml file:

    dependencies:
      customer_io: ^2.2.0
    
  2. Run dependency update:

    flutter pub get && cd ios && pod install --repo-update && cd ..
    

Update with FCM (Firebase Cloud Messaging)

Update your AppDelegate.swift file to use the new CioAppDelegateWrapper pattern. See the Before sample to see what needs to change and the After sample to see the new pattern.

import UIKit
import Flutter
import CioMessagingPushFCM
import FirebaseMessaging
import FirebaseCore

@main
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        
        Messaging.messaging().delegate = self
        
        MessagingPushFCM.initialize(
            withConfig: MessagingPushConfigBuilder()
                .build()
        )
        
        UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate

        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    func application(application: UIApplication,
                    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().setAPNSToken(deviceToken, type: .unknown);
    }
    
    override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        MessagingPush.shared.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
    }
}

extension AppDelegate: MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        MessagingPush.shared.messaging(messaging, didReceiveRegistrationToken: fcmToken)
    }
}
import UIKit
import Flutter
import CioMessagingPushFCM
import FirebaseMessaging
import FirebaseCore

@main
class AppDelegateWithCioIntegration: CioAppDelegateWrapper<AppDelegate> {}

class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        
        // Initialize push with wrapper - handles all push methods automatically
        MessagingPushFCM.initialize(
            withConfig: MessagingPushConfigBuilder()
                .build()
        )

        // Optional: Add only if you want custom control over notifications
        UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    override func application(_ application: UIApplication,
                              didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
        
        Messaging.messaging().apnsToken = deviceToken
    }
    
    // No manual push methods needed - CioAppDelegateWrapper handles everything
}

Configuration Options

You can customize the push behavior when you initialize your push package:

MessagingPushFCM.initialize(
    withConfig: MessagingPushConfigBuilder()
        .showPushAppInForeground(true)  // Show push when app is in foreground
        .autoTrackPushEvents(true)       // Automatically track push metrics
        .build()
)

Important Notes

  1. Manual push handling methods are not required: the CioAppDelegateWrapper automatically records information from following methods. But you can still use these methods if you want to add custom push handling:

    • didRegisterForRemoteNotificationsWithDeviceToken
    • didFailToRegisterForRemoteNotificationsWithError
    • All other push-related delegate methods
  2. The @main attribute - Must be on the wrapper class, not your AppDelegate.

  3. Flutter-specific: Your Flutter app’s main.dart file doesn’t need any changes.

  4. NotificationService.swift remains unchanged - Your notification service extension configuration works the same with both approaches.

Troubleshooting

If push notifications stop working after you update your implementation:

  1. Make sure that you’ve added the @main attribute to the wrapper class
  2. Verify that you’ve removed @main from your original AppDelegate
  3. Check that you’re calling MessagingPushFCM.initialize()
  4. Run flutter clean followed by pod install --repo-update --project-directory=ios
  5. Test on a physical device (push notifications don’t work on simulators)
Copied to clipboard!
  Contents
Version
Is this page helpful?