Skip to content

[UIScene] Forward scene lifecycle events to plugins #174398

@vashworth

Description

@vashworth

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;
}
@end

See prototype.

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listplatform-iosiOS applications specificallyteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions