diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h b/engine/src/flutter/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h index 43c88215d3f..038db1f322e 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h @@ -53,7 +53,18 @@ FLUTTER_DARWIN_EXPORT bundle:(nullable NSBundle*)nibBundleOrNil NS_DESIGNATED_INITIALIZER; - (nonnull instancetype)initWithCoder:(nonnull NSCoder*)nibNameOrNil NS_DESIGNATED_INITIALIZER; - +/** + * Initializes this FlutterViewController with the specified `FlutterEngine`. + * + * The initialized viewcontroller will attach itself to the engine as part of this process. + * + * @param engine The `FlutterEngine` instance to attach to. Cannot be nil. + * @param nibName The NIB name to initialize this controller with. + * @param nibBundle The NIB bundle. + */ +- (nonnull instancetype)initWithEngine:(nonnull FlutterEngine*)engine + nibName:(nullable NSString*)nibName + bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER; /** * Invoked by the engine right before the engine is restarted. * diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index bf13f616782..cb472018404 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -329,18 +329,21 @@ static void CommonInit(FlutterViewController* controller) { nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle { NSAssert(engine != nil, @"Engine is required"); + NSAssert(engine.viewController == nil, + @"The supplied FlutterEngine is already used with FlutterViewController " + "instance. One instance of the FlutterEngine can only be attached to one " + "FlutterViewController at a time. Set FlutterEngine.viewController " + "to nil before attaching it to another FlutterViewController."); + self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { - if (engine.viewController) { - NSLog(@"The supplied FlutterEngine %@ is already used with FlutterViewController " - "instance %@. One instance of the FlutterEngine can only be attached to one " - "FlutterViewController at a time. Set FlutterEngine.viewController " - "to nil before attaching it to another FlutterViewController.", - [engine description], [engine.viewController description]); - } _engine = engine; CommonInit(self); - [engine setViewController:self]; + if (engine.running) { + [self loadView]; + engine.viewController = self; + [self initializeKeyboard]; + } } return self; diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm index 5905600b6d1..eb373819a8f 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm @@ -23,6 +23,7 @@ - (bool)testKeyboardIsRestartedOnEngineRestart; - (bool)testTrackpadGesturesAreSentToFramework; - (bool)testViewWillAppearCalledMultipleTimes; +- (bool)testFlutterViewIsConfigured; + (void)respondFalseForSendEvent:(const FlutterKeyEvent&)event callback:(nullable FlutterKeyEventCallback)callback @@ -164,6 +165,10 @@ TEST(FlutterViewControllerTest, testViewWillAppearCalledMultipleTimes) { ASSERT_TRUE([[FlutterViewControllerTestObjC alloc] testViewWillAppearCalledMultipleTimes]); } +TEST(FlutterViewControllerTest, testFlutterViewIsConfigured) { + ASSERT_TRUE([[FlutterViewControllerTestObjC alloc] testFlutterViewIsConfigured]); +} + } // namespace flutter::testing @implementation FlutterViewControllerTestObjC @@ -261,6 +266,27 @@ TEST(FlutterViewControllerTest, testViewWillAppearCalledMultipleTimes) { return true; } +- (bool)testFlutterViewIsConfigured { + id engineMock = OCMClassMock([FlutterEngine class]); + + id renderer_ = [[FlutterMetalRenderer alloc] initWithFlutterEngine:engineMock]; + OCMStub([engineMock renderer]).andReturn(renderer_); + + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + [viewController loadView]; + + @try { + // Make sure "renderer" was called during "loadView", which means "flutterView" is created + OCMVerify([engineMock renderer]); + } @catch (...) { + return false; + } + + return true; +} + - (bool)testFlagsChangedEventsArePropagatedIfNotHandled { id engineMock = OCMClassMock([FlutterEngine class]); id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h index 04ed474602c..19870cf5b18 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h @@ -18,19 +18,6 @@ */ @property(nonatomic, readonly, nonnull) FlutterTextInputPlugin* textInputPlugin; -/** - * Initializes this FlutterViewController with the specified `FlutterEngine`. - * - * The initialized viewcontroller will attach itself to the engine as part of this process. - * - * @param engine The `FlutterEngine` instance to attach to. Cannot be nil. - * @param nibName The NIB name to initialize this controller with. - * @param nibBundle The NIB bundle. - */ -- (nonnull instancetype)initWithEngine:(nonnull FlutterEngine*)engine - nibName:(nullable NSString*)nibName - bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER; - /** * Returns YES if provided event is being currently redispatched by keyboard manager. */