Skip to content

Consider continuing to use FlutterLaunchEngine for FlutterImplicitEngine callback #184267

@vashworth

Description

@vashworth

Currently, when migrating to UIScene, you add the FlutterImplicitEngineDelegate to your AppDelegate and add a didInitializeImplicitFlutterEngine callback. This callback is called when the FlutterEngine is created by the FlutterViewController, primarily from a storyboard.

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

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

BOOL performedCallback = [_engine performImplicitEngineCallback];

This change was made due the Storyboard initializing later in the lifecycle than before. It now initializes after application:didFinishLaunchingWithOptions:.

However, due to this, plugins cannot receive application:didFinishLaunchingWithOptions: event because the engine is not created yet.

To work around this, we call those methods once the engine is created by the storyboard

// When migrated to scenes, the FlutterViewController from the storyboard is initialized after the
// application launch events. Therefore, plugins may not be registered yet since they're expected
// to be registered during the implicit engine callbacks. As a workaround, send the app launch
// events after the application callbacks.
if (self.awokenFromNib && performedCallback && FlutterSharedApplication.hasSceneDelegate &&
[appDelegate isKindOfClass:[FlutterAppDelegate class]]) {
id applicationLifeCycleDelegate = ((FlutterAppDelegate*)appDelegate).lifeCycleDelegate;
[applicationLifeCycleDelegate
sceneFallbackWillFinishLaunchingApplication:FlutterSharedApplication.application];
[applicationLifeCycleDelegate
sceneFallbackDidFinishLaunchingApplication:FlutterSharedApplication.application];
}

However, this seem to be problematic:

May also be related: #183900

When first investigating UIScene, FlutterLaunchEngine was introduced. This allowed plugins to still be registered in application:didFinishLaunchingWithOptions: by creating a FlutterEngine and saving it to the FlutterAppDelegate, which can be accessed via the singleton app instance. Then once the FlutterViewController initializes, it will “take” the FlutterEngine from the FlutterAppDelegate instead of creating one.

There was some disagreement on the API, though, which is why we changed to this.

https://flutter.dev/go/ios-ui-scene-lifecycle-migration
go/flutter-ios-uiscene-delegate-adoption-v1

I wonder if there's some way we could still use the FlutterLaunchEngine but still with the FlutterImplicitEngineDelegate

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority issues at the top of the work lista: pluginsSupport for writing, building, and running plugin packagesengineflutter/engine related. See also e: labels.platform-iosiOS applications specificallyteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions