Skip to content

Add Native Support for UISceneDelegate for Flutter Integration #485

@ik-make

Description

@ik-make

Describe the feature

Summary

First of all, thank you for maintaining this Flutter plugin! We've been using flutter_branch_sdk successfully in our production app for deep linking and attribution.

We'd like to request native support for UISceneDelegate on iOS. This is becoming increasingly important as Apple is transitioning away from the traditional AppDelegate-only lifecycle, and Flutter has already adopted UISceneDelegate as the default for new iOS projects.


Context & Motivation

Apple's Direction

Apple introduced UISceneDelegate in iOS 13 to support multi-window applications and improve app lifecycle management. Starting with recent iOS versions, Apple has been displaying the following warning:

⚠️ "UIScene lifecycle will soon be required. Failure to adopt will result in an assert in the future."

This indicates that Apple is moving toward making UISceneDelegate mandatory, and apps relying solely on AppDelegate lifecycle methods may face compatibility issues in future iOS releases.

Apple Documentation:

Flutter's Adoption

Flutter has officially adopted UISceneDelegate as part of their iOS integration. The Flutter team has published breaking change documentation outlining this transition:

Flutter Documentation:

New Flutter projects created with recent versions of Flutter use SceneDelegate by default, making this integration pattern the standard for Flutter iOS apps going forward.


Current Behavior

The plugin's README states:

"iOS Integration
Follow only the steps:

Configure bundle identifier
Configure associated domains
Configure Info.plist"

That means no need to add any code in AppDelegate or SceneDelegate

However, in practice, when using SceneDelegate:

  1. The plugin's application(_:didFinishLaunchingWithOptions:) method sets up the Branch.getInstance().initSession() callback
  2. This callback is registered via FlutterPluginAppLifeCycleDelegate forwarding
  3. With SceneDelegate, the deep link entry points are scene methods (scene(_:continue:), scene(_:openURLContexts:)), not AppDelegate methods
  4. The plugin does not implement UISceneDelegate methods, so deep link data doesn't flow through to the Flutter listener

Result: +clicked_branch_link is always false, and handleBranchDeepLink in Flutter never receives valid deep link data when using SceneDelegate.


Expected Behavior

When using SceneDelegate, the plugin should:

  1. Properly receive deep link events from scene lifecycle methods
  2. Forward deep link data to Flutter's FlutterBranchSdk.listSession() stream
  3. Set +clicked_branch_link: true when the app is opened via a Branch link

Environment

  • flutter_branch_sdk version: 8.8.0
  • Flutter version: 3.x
  • iOS version: 17+
  • Xcode version: 15+

Reproduction Steps

  1. Create a Flutter app with UISceneDelegate enabled (default in new Flutter projects)
  2. Integrate flutter_branch_sdk following the README
  3. Configure Branch deep links
  4. Click a Branch link to open the app
  5. Observe that FlutterBranchSdk.listSession() returns +clicked_branch_link: false

Workaround Attempted

We've tried manually calling Branch.getInstance().continue(userActivity) and Branch.getInstance().handleDeepLink(withNewSession: url) from SceneDelegate, but the plugin's callback isn't connected because the lifecycle forwarding doesn't work with custom engines in SceneDelegate architecture.

The only working solution currently is to remove SceneDelegate entirely and use AppDelegate-only lifecycle, which conflicts with:

  • Apple's direction toward mandatory UIScene lifecycle
  • Modern Flutter's engine requirements

Additional Context

Branch.io Native iOS Documentation:

Related Discussions:

  • Flutter Engine's SceneDelegate support has been evolving, with discussions on proper plugin lifecycle handling

Thank You! 🙏

Adding SceneDelegate support would help ensure the plugin remains compatible with Apple's evolving iOS architecture and Flutter's default project setup.

Happy to help test any beta releases or provide additional debugging information!


Checklist Before Submitting

  • Searched existing issues to avoid duplicates
  • Provided clear reproduction steps
  • Included relevant version information
  • Used constructive, positive language
  • Offered to help with testing

Describe the solution you'd like


Proposed Solution

We propose adding support for scene-based lifecycle methods. The native Branch iOS SDK already provides BranchScene API for this purpose:

// In SceneDelegate
import BranchSDK

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    BranchScene.shared().scene(scene, continue: userActivity)
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    BranchScene.shared().scene(scene, openURLContexts: URLContexts)
}

Possible implementation approaches:

  1. Add FlutterSceneDelegate support: Implement scene lifecycle methods that plugins can register for (similar to addApplicationDelegate)

  2. Provide scene-aware initialization: Allow BranchScene.shared().initSession() to be used instead of Branch.getInstance().initSession() when the app uses SceneDelegate

  3. Documentation update: If manual native code is required, provide clear documentation for SceneDelegate integration


Can you submit a pull request?

No

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions