Add isDisplayingFlutterUI to FlutterViewController (flutter/engine#10816)

This commit is contained in:
Dan Field 2019-08-14 09:10:22 -07:00 committed by GitHub
parent 89f22f0144
commit 16c2058bf2
3 changed files with 45 additions and 9 deletions

View File

@ -130,6 +130,14 @@ FLUTTER_EXPORT
*/
- (id<FlutterPluginRegistry>)pluginRegistry;
/**
* True if at least one frame has rendered and the ViewController has appeared.
*
* This property is reset to false when the ViewController disappears. It is
* guaranteed to only alternate between true and false for observers.
*/
@property(nonatomic, readonly, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI;
/**
* Specifies the view to use as a splash screen. Flutter's rendering is asynchronous, so the first
* frame rendered by the Flutter application might not immediately appear when theFlutter view is

View File

@ -29,6 +29,7 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
// change. Unfortunately unless you have Werror turned on, incompatible pointers as arguments are
// just a warning.
@interface FlutterViewController () <FlutterBinaryMessenger>
@property(nonatomic, readwrite, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI;
@end
@implementation FlutterViewController {
@ -49,6 +50,8 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
NSMutableSet<NSNumber*>* _ongoingTouches;
}
@synthesize displayingFlutterUI = _displayingFlutterUI;
#pragma mark - Manage and override all designated initializers
- (instancetype)initWithEngine:(FlutterEngine*)engine
@ -263,7 +266,25 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
[self.view addSubview:splashScreenView];
}
+ (BOOL)automaticallyNotifiesObserversOfDisplayingFlutterUI {
return NO;
}
- (void)setDisplayingFlutterUI:(BOOL)displayingFlutterUI {
if (_displayingFlutterUI != displayingFlutterUI) {
if (displayingFlutterUI == YES) {
if (!self.isViewLoaded || !self.view.window) {
return;
}
}
[self willChangeValueForKey:@"displayingFlutterUI"];
_displayingFlutterUI = displayingFlutterUI;
[self didChangeValueForKey:@"displayingFlutterUI"];
}
}
- (void)callViewRenderedCallback {
self.displayingFlutterUI = YES;
if (_flutterViewRenderedCallback != nil) {
_flutterViewRenderedCallback.get()();
_flutterViewRenderedCallback.reset();
@ -395,6 +416,7 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
[_engine.get() platformViewsController] -> SetFlutterViewController(self);
[_engine.get() platformView] -> NotifyCreated();
} else {
self.displayingFlutterUI = NO;
[_engine.get() platformView] -> NotifyDestroyed();
[_engine.get() platformViewsController] -> SetFlutterView(nullptr);
[_engine.get() platformViewsController] -> SetFlutterViewController(nullptr);

View File

@ -25,25 +25,31 @@
}
- (void)testFirstFrameCallback {
XCTestExpectation* firstFrameRendered = [self expectationWithDescription:@"firstFrameRendered"];
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
[engine runWithEntrypoint:nil];
self.flutterViewController = [[FlutterViewController alloc] initWithEngine:engine
nibName:nil
bundle:nil];
__block BOOL shouldKeepRunning = YES;
XCTAssertFalse(self.flutterViewController.isDisplayingFlutterUI);
XCTestExpectation* displayingFlutterUIExpectation =
[self keyValueObservingExpectationForObject:self.flutterViewController
keyPath:@"displayingFlutterUI"
expectedValue:@YES];
displayingFlutterUIExpectation.assertForOverFulfill = YES;
[self.flutterViewController setFlutterViewDidRenderCallback:^{
shouldKeepRunning = NO;
[firstFrameRendered fulfill];
}];
AppDelegate* appDelegate = (AppDelegate*)UIApplication.sharedApplication.delegate;
UIViewController* rootVC = appDelegate.window.rootViewController;
[rootVC presentViewController:self.flutterViewController animated:NO completion:nil];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
int countDownMs = 2000;
while (shouldKeepRunning && countDownMs > 0) {
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
countDownMs -= 100;
}
XCTAssertGreaterThan(countDownMs, 0);
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
@end