From 3ffa362952340ddee3febb0efa9599091c0d2fc6 Mon Sep 17 00:00:00 2001 From: "James D. Lin" Date: Thu, 11 Oct 2018 20:21:13 -0700 Subject: [PATCH] Add a callback for iOS when the first Flutter frame is rendered (#6135) Add a `-[FlutterViewController setFlutterViewDidRenderCallback:]` method on iOS so client applications can be notified when the Flutter view has rendered. This can be used for add2app cases to determine when to take an initial screenshot for comparisons in automated tests. The callback is expected to be an Objective-C block (or Swift closure). I chose to support only a single callback because it's much simpler (especially since it does not require a separate method to unregister the callback), and it's not clear that there are use cases that would justify additional complexity. Clients have the flexibility to make their callback invoke other callbacks anyway. I alternatively considered adding a `-[FlutterViewController viewDidRenderFirstFlutterFrame]` method that clients could override in a subclass, but using an Objective-C block seems more flexible and less of a burden. Fixes https://github.com/flutter/flutter/issues/20665 --- .../darwin/ios/framework/Headers/FlutterViewController.h | 8 ++++++++ .../darwin/ios/framework/Source/FlutterViewController.mm | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h index 2e8b02d0519..5459c17f4f8 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h @@ -24,6 +24,14 @@ FLUTTER_EXPORT - (void)handleStatusBarTouches:(UIEvent*)event; +/** + Registers a callback that will be invoked when the Flutter view has been rendered. + The callback will be fired only once. + + Replaces an existing callback. Use a `nil` callback to unregister the existing one. + */ +- (void)setFlutterViewDidRenderCallback:(void (^)(void))callback; + /** Returns the file name for the given asset. The returned file name can be used to access the asset in the application's main bundle. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 471e88e2dc5..ccbee6eebe8 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -51,6 +51,7 @@ // setup a shell along with its platform view before the view has to appear. fml::scoped_nsobject _flutterView; fml::scoped_nsobject _splashScreenView; + fml::ScopedBlock _flutterViewRenderedCallback; UIInterfaceOrientationMask _orientationPreferences; UIStatusBarStyle _statusBarStyle; blink::ViewportMetrics _viewportMetrics; @@ -367,6 +368,10 @@ completion:^(BOOL finished) { [_splashScreenView.get() removeFromSuperview]; _splashScreenView.reset(); + if (_flutterViewRenderedCallback != nil) { + _flutterViewRenderedCallback.get()(); + _flutterViewRenderedCallback.reset(); + } }]; } @@ -443,6 +448,10 @@ UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; } +- (void)setFlutterViewDidRenderCallback:(void (^)(void))callback { + _flutterViewRenderedCallback.reset(callback, fml::OwnershipPolicy::Retain); +} + #pragma mark - Surface creation and teardown updates - (void)surfaceUpdated:(BOOL)appeared {