Skip to content

iOS‐SceneDelegate Integration

Savitha Rudramuni edited this page Dec 8, 2025 · 1 revision

Overview

This guide provides steps for configuring your iOS mobile app with Scene Delegate.

To complete the steps, you will need to configure following flutter dependency in pubspec.yaml, if not done already.

Requirements

environment:
  sdk: ^3.10.0
  flutter: ">=3.38.0"

dependencies:
pushiomanager_flutter:
      git:
          url: https://github.com/oracle-samples/pushiomanager-flutter.git

Supported Plugin and SDK Versions

Flutter plugin version : 7.0.0
Responsys SDK version : 7.0.2

Project Setup

1. Enable Scene Manifest in Info.plist

To complete the migration to the UIScene lifecycle, add an Application Scene Manifest to your Info.plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>UIApplicationSceneManifest</key>
 <dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <false/>
  <key>UISceneConfigurations</key>
  <dict>
  <key>UIWindowSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneClassName</key>
        <string>UIWindowScene</string>
        <key>UISceneDelegateClassName</key>
        <string>FlutterSceneDelegate</string>
        <key>UISceneConfigurationName</key>
        <string>flutter</string>
        <key>UISceneStoryboardFile</key>
        <string>Main</string>
      </dict>
    </array>
   </dict>
 </dict>
</dict>

2. Migrate AppDelegate

Previously, Flutter plugins were registered in application:didFinishLaunchingWithOptions:. To accomodate the new app launch sequence, plugin registration must now be handled in a new callback called didInitializeImplicitFlutterEngine.

Swift

@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
  GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}

Objective-C

//AppDelegate.h

#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate <FlutterImplicitEngineDelegate>

@end

//AppDelegate.m

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)didInitializeImplicitFlutterEngine:(NSObject<FlutterImplicitEngineBridge>*)engineBridge {
  [GeneratedPluginRegistrant registerWithRegistry:engineBridge.pluginRegistry];
}


@end

3. Create SceneDelegate(Optional)

If app developer does not implement SceneDelegate methods(such as deeplink or push notification handling) flutter apps still continue to work because flutter provides an internal fallback mechanism using AppDelegate and FlutterEngine lifecyle.

If SceneDelegate does not implement scene:openURLContexts: then the deep link event is routed to AppDelegate’s application:openURL:options:.

If you still need access to the SceneDelegate, you can create one by subclassing FlutterSceneDelegate.

SceneDelegate.swift

import Flutter
import UIKit

class SceneDelegate: FlutterSceneDelegate {
 
}

Note: Change the "Delegate Class Name" (UISceneDelegateClassName) in the Info.plist from FlutterSceneDelegate to $(PRODUCT_MODULE_NAME).SceneDelegate.

SceneDelegate.m

#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface SceneDelegate : FlutterSceneDelegate

@end

#import "SceneDelegate.h"

@implementation SceneDelegate

@end

Note: Change the "Delegate Class Name" (UISceneDelegateClassName) in the Info.plist from FlutterSceneDelegate to SceneDelegate.

4. Deeplink Handling in SceneDelegate

This replaces :application(_:open:options:) when SceneDelegate is used.

SceneDelegate.swift

import Flutter
import UIKit
import CX_Mobile_SDK

class SceneDelegate: FlutterSceneDelegate {
    
    override func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
         PushIOManager.sharedInstance().openURLContexts(URLContexts);
    }
}

SceneDelegate.m

#import "SceneDelegate.h"
#import <CX_Mobile_SDK/CX_Mobile_SDK.h>

@implementation SceneDelegate


- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
      [[PushIOManager sharedInstance] openURLContexts:URLContexts];
}

@end

5. Push Notification Handling in SceneDelegate

Handling UNUserNotificationCenterDelegate in SceneDelegate is essential for scene-based iOS apps to correctly receive and respond to push notifications.To ensure that notification actions and taps are properly delivered, SceneDelegate must be configured to adopt UNUserNotificationCenterDelegate and register itself as the delegate.

SceneDelegate.swift

import Flutter
import UIKit
import CX_Mobile_SDK

class SceneDelegate: FlutterSceneDelegate,UNUserNotificationCenterDelegate {
    
    override func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        UNUserNotificationCenter.current().delegate = self
    }

    func userNotificationCenter(
       _ center: UNUserNotificationCenter,
       didReceive response: UNNotificationResponse,
       withCompletionHandler completionHandler: @escaping () -> Void
   ) {
        PushIOManager.sharedInstance().userNotificationCenter(center, didReceive: response);
   }

     func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping     (UNNotificationPresentationOptions) -> Void) {
        PushIOManager.sharedInstance().userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler);
    }
}

SceneDelegate.m

@interface SceneDelegate : FlutterSceneDelegate<UNUserNotificationCenterDelegate>

@end

#import "SceneDelegate.h"
#import <CX_Mobile_SDK/CX_Mobile_SDK.h>

@implementation SceneDelegate


- (void)scene:(UIScene*)scene
    willConnectToSession:(UISceneSession*)session
                options:(UISceneConnectionOptions*)connectionOptions {
    [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler{
    [[PushIOManager sharedInstance]userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
    [[PushIOManager sharedInstance]userNotificationCenter:center willPresentNotification:notification withCompletionHandler:completionHandler];
}

@end

Reference

Flutter:SceneDelegate-Setup