-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Closed
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listplatform-iosiOS applications specificallyiOS applications specificallyteam-iosOwned by iOS platform teamOwned by iOS platform teamtriaged-iosTriaged by iOS platform teamTriaged by iOS platform team
Description
Problem
Flutter forwards application lifecycle events to plugins. After migrating to scenes, application lifecycle events may not work the same as before. Therefore, we need to migrate to scene lifecycle events.
Prerequisites
Proposal
Introduce a FlutterPluginSceneLifeCycleDelegate to FlutterEngine. FlutterPluginSceneLifeCycleDelegate will hold a weak array to all registered plugins.
The FlutterSceneDelegate will forward scene lifecycle events to all associated engines, which will then forward the event to the FlutterPluginSceneLifeCycleDelegate, which will then forward the events to the plugins.
FlutterSceneDelegate.mm:
- (void)sceneDidBecomeActive:(UIScene*)scene {
for (FlutterEngine* engine in [_engines allObjects]) {
if (!engine) {
continue;
}
[engine.sceneLifeCycleDelegate sceneDidBecomeActive:scene];
}
}@implementation FlutterPluginSceneLifeCycleDelegate {
// Weak references to registered plugins.
NSPointerArray* _delegates;
}
- (instancetype)init {
if (self = [super init]) {
_delegates = [NSPointerArray weakObjectsPointerArray];
}
return self;
}
- (void)addDelegate:(NSObject<FlutterSceneLifeCycleDelegate>*)delegate {
[_delegates addPointer:(__bridge void*)delegate];
if (IsPowerOfTwo([_delegates count])) {
[_delegates compact];
}
}
- (void)flutterViewController:(FlutterViewController*)controller
didConnectToScene:(UIScene*)scene
options:(UISceneConnectionOptions*)connectionOptions {
for (NSObject<FlutterSceneLifeCycleDelegate>* delegate in [_delegates allObjects]) {
if (!delegate) {
continue;
}
if ([delegate respondsToSelector:_cmd]) {
[delegate flutterViewController:controller didConnectToScene:scene options:connectionOptions];
}
}
}
- (void)sceneDidBecomeActive:(UIScene*)scene {
for (NSObject<FlutterSceneLifeCycleDelegate>* delegate in [_delegates allObjects]) {
if (!delegate) {
continue;
}
if ([delegate respondsToSelector:_cmd]) {
[delegate sceneDidBecomeActive:scene];
} else {
// TODO: Fallback to application callback
}
}
}
- (void)windowScene:(UIWindowScene*)windowScene
performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler {
FlutterPluginAppLifeCycleDelegate* appLifeCycleDelegate = [self applicationLifeCycleDelegate];
for (NSObject<FlutterSceneLifeCycleDelegate>* delegate in [_delegates allObjects]) {
if (!delegate) {
continue;
}
if ([delegate respondsToSelector:_cmd]) {
[delegate windowScene:windowScene
performActionForShortcutItem:shortcutItem
completionHandler:completionHandler];
} else {
// Fallback to application callback
if (appLifeCycleDelegate != nil) {
[FlutterLogger
logWarning:
@"Plugin does not support scene. Falling back to application lifecycle event."];
[appLifeCycleDelegate application:FlutterSharedApplication.application
performActionForShortcutItem:shortcutItem
completionHandler:completionHandler];
} else {
[FlutterLogger logWarning:@"Plugin does not support scene"];
}
}
}
}
...
- (FlutterPluginAppLifeCycleDelegate*)applicationLifeCycleDelegate {
id appDelegate = FlutterSharedApplication.application.delegate;
FlutterPluginAppLifeCycleDelegate* lifeCycleDelegate = nil;
if ([appDelegate respondsToSelector:@selector(lifeCycleDelegate)]) {
lifeCycleDelegate = [appDelegate lifeCycleDelegate];
}
return lifeCycleDelegate;
}
@endSee prototype.
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listplatform-iosiOS applications specificallyiOS applications specificallyteam-iosOwned by iOS platform teamOwned by iOS platform teamtriaged-iosTriaged by iOS platform teamTriaged by iOS platform team