Skip to content

[UIScene] Associate the FlutterEngine with FlutterSceneDelegate #174395

@vashworth

Description

@vashworth

Problem

Flutter does certain things in response to lifecycle events. After migrating to scenes, application lifecycle events may not work the same as before. Therefore, we need to migrate to scene lifecycle events. However, we need to consider that there could be multiple scene, which could have multiple engines. As such, we should track engines that are associated with the scene.

Proposal

When a FlutterViewController is added to the scene, we should add its FlutterEngine to the FlutterSceneDelegate.

FlutterSceneDelegate.mm:

_engines = [NSPointerArray weakObjectsPointerArray];

...

- (void)addFlutterViewController:(FlutterViewController*)controller {
  NSLog(@"Engine added to scene");

  // NSPointerArray is clever and assumes that unless a mutation operation has occurred on it that
  // has set one of its values to nil, nothing could have changed and it can skip compaction.
  // That's reasonable behaviour on a regular NSPointerArray but not for a weakObjectPointerArray.
  // As a workaround, we mutate it first. See: http://www.openradar.me/15396578
  [self.engines addPointer:nil];
  [self.engines compact];

  // Check if the engine is already in the array to avoid duplicates.
  if (![self.engines.allObjects containsObject:controller.engine]) {
    [self.engines addPointer:(__bridge void*)controller.engine];
  }

  [controller.engine.sceneLifeCycleDelegate flutterViewController:controller
                                                didConnectToScene:(UIScene*)self
                                                          options:self.sceneConnectionOptions];
}

FlutterViewController:

- (void)viewIsAppearing:(BOOL)animated {
  FML_LOG(ERROR) << "viewIsAppearing";
  [self connectFlutterViewControllerWithScene];
  [super viewIsAppearing:animated];
}

- (void)connectFlutterViewControllerWithScene {
  // The scene is not available until viewIsAppearing
  UIWindowScene* scene = self.view.window.windowScene;

  // self.view.window.windowScene
  if ([scene.delegate conformsToProtocol:@protocol(FlutterSceneLifeCycleProvider)]) {
    id<FlutterSceneLifeCycleProvider> lifeCycleProvider =
        (id<FlutterSceneLifeCycleProvider>)scene.delegate;
    [lifeCycleProvider addFlutterViewController:self];
  }
}

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