Skip to content

Commit

Permalink
Add a callback for iOS when the first Flutter frame is rendered (flut…
Browse files Browse the repository at this point in the history
…ter#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 flutter/flutter#20665
  • Loading branch information
jamesderlin authored Oct 12, 2018
1 parent 35ba11e commit 3ffa362
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ @implementation FlutterViewController {
// setup a shell along with its platform view before the view has to appear.
fml::scoped_nsobject<FlutterView> _flutterView;
fml::scoped_nsobject<UIView> _splashScreenView;
fml::ScopedBlock<void (^)(void)> _flutterViewRenderedCallback;
UIInterfaceOrientationMask _orientationPreferences;
UIStatusBarStyle _statusBarStyle;
blink::ViewportMetrics _viewportMetrics;
Expand Down Expand Up @@ -367,6 +368,10 @@ - (void)removeSplashScreenViewIfPresent {
completion:^(BOOL finished) {
[_splashScreenView.get() removeFromSuperview];
_splashScreenView.reset();
if (_flutterViewRenderedCallback != nil) {
_flutterViewRenderedCallback.get()();
_flutterViewRenderedCallback.reset();
}
}];
}

Expand Down Expand Up @@ -443,6 +448,10 @@ - (void)setSplashScreenView:(UIView*)view {
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}

- (void)setFlutterViewDidRenderCallback:(void (^)(void))callback {
_flutterViewRenderedCallback.reset(callback, fml::OwnershipPolicy::Retain);
}

#pragma mark - Surface creation and teardown updates

- (void)surfaceUpdated:(BOOL)appeared {
Expand Down

0 comments on commit 3ffa362

Please sign in to comment.