[macos] expose runWithEngine constructor in FlutterViewController

Removing [engine setViewController:self]; because view is not loaded, but in that function controller is saved. Later, when the view is loaded (loadView) passed as an argument controller is checked against the saved controller and since they match, the nil view is not replaced with a new view.

Fixes: flutter/flutter#74735
This commit is contained in:
sergiy-sc 2022-10-14 16:04:36 +03:00 committed by GitHub
parent 5da875e4c9
commit 64a8156560
4 changed files with 49 additions and 22 deletions

View File

@ -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.
*

View File

@ -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;

View File

@ -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));

View File

@ -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.
*/