diff --git a/src/content/platform-integration/ios/platform-views.md b/src/content/platform-integration/ios/platform-views.md index f18c0c913c..9c4d88181e 100644 --- a/src/content/platform-integration/ios/platform-views.md +++ b/src/content/platform-integration/ios/platform-views.md @@ -169,21 +169,18 @@ modify the App's `AppDelegate.swift`: import Flutter import UIKit -@UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) +@main +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) - guard let pluginRegistrar = self.registrar(forPlugin: "plugin-name") else { return false } + guard let pluginRegistrar = engineBridge.pluginRegistry.registrar(forPlugin: "plugin-name") else { return } let factory = FLNativeViewFactory(messenger: pluginRegistrar.messenger()) pluginRegistrar.register( factory, withId: "") - return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } ``` @@ -298,19 +295,16 @@ modify the App's `AppDelegate.m`: @implementation AppDelegate -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; +- (void)didInitializeImplicitFlutterEngine:(NSObject*)engineBridge { + [GeneratedPluginRegistrant registerWithRegistry:engineBridge.pluginRegistry]; - NSObject* registrar = - [self registrarForPlugin:@"plugin-name"]; + NSObject* registrar = + [engineBridge.pluginRegistry registrarForPlugin:@"plugin-name"]; FLNativeViewFactory* factory = [[FLNativeViewFactory alloc] initWithMessenger:registrar.messenger]; - [[self registrarForPlugin:@""] registerViewFactory:factory - withId:@""]; - return [super application:application didFinishLaunchingWithOptions:launchOptions]; + [registrar registerViewFactory:factory withId:@""]; } @end diff --git a/src/content/platform-integration/platform-channels.md b/src/content/platform-integration/platform-channels.md index 67e27eac9c..61f6c86b50 100644 --- a/src/content/platform-integration/platform-channels.md +++ b/src/content/platform-integration/platform-channels.md @@ -612,24 +612,30 @@ Override the `application:didFinishLaunchingWithOptions:` function and create a `FlutterMethodChannel` tied to the channel name `samples.flutter.dev/battery`: +:::note +If your app adopts the `UISceneDelegate` lifecycle (default in Flutter 3.41+), +`window` will be `nil` during `application(_:didFinishLaunchingWithOptions:)`. +To avoid a crash, use the `FlutterImplicitEngineDelegate` protocol and +create your `FlutterMethodChannel` in the `didInitializeImplicitFlutterEngine` method. +::: + ```swift title="AppDelegate.swift" @main -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - - let controller : FlutterViewController = window?.rootViewController as! FlutterViewController - let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery", - binaryMessenger: controller.binaryMessenger) +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + + let batteryChannel = FlutterMethodChannel( + name: "samples.flutter.dev/battery", + binaryMessenger: engineBridge.applicationRegistrar.messenger() + ) + batteryChannel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in // This method is invoked on the UI thread. // Handle battery messages. }) - - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } ``` @@ -695,26 +701,32 @@ didFinishLaunchingWithOptions:` method. Make sure to use the same channel name as was used on the Flutter client side. +:::note +If your app adopts the `UISceneDelegate` lifecycle (default in Flutter 3.41+), +`window` will be `nil` during `application:didFinishLaunchingWithOptions:`. +To avoid a crash, use the `FlutterImplicitEngineDelegate` protocol and +create your `FlutterMethodChannel` in the `didInitializeImplicitFlutterEngine` method. +::: + ```objc title="AppDelegate.m" #import #import "GeneratedPluginRegistrant.h" @implementation AppDelegate -- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { - FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; + +- (void)didInitializeImplicitFlutterEngine:(NSObject*)engineBridge { + [GeneratedPluginRegistrant registerWithRegistry:engineBridge.pluginRegistry]; FlutterMethodChannel* batteryChannel = [FlutterMethodChannel - methodChannelWithName:@"samples.flutter.dev/battery" - binaryMessenger:controller.binaryMessenger]; + methodChannelWithName:@"samples.flutter.dev/battery" + binaryMessenger:engineBridge.applicationRegistrar.messenger]; [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { // This method is invoked on the UI thread. // TODO }]; - - [GeneratedPluginRegistrant registerWithRegistry:self]; - return [super application:application didFinishLaunchingWithOptions:launchOptions]; } +@end ``` Next, add the iOS ObjectiveC code that uses the iOS battery APIs to