diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index b69ce5123a9..928bab11846 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -393,7 +393,6 @@ static constexpr int kNumProfilerSamplesPerSec = 5; - (void)attachView { self.iosPlatformView->attachView(); - [_textInputPlugin.get() setupIndirectScribbleInteraction:self.viewController]; } - (void)setFlutterViewControllerWillDeallocObserver:(id)observer { diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 48868dbd4b7..9834d47fdf3 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -676,15 +676,13 @@ static void SendFakeTouchEvent(FlutterEngine* engine, [_engine.get() launchEngine:nil libraryURI:nil entrypointArgs:nil]; [_engine.get() setViewController:self]; _engineNeedsLaunch = NO; + } else if ([_engine.get() viewController] == self) { + [_engine.get() attachView]; } // Register internal plugins. [self addInternalPlugins]; - if ([_engine.get() viewController] == self) { - [_engine.get() attachView]; - } - if (@available(iOS 13.4, *)) { _hoverGestureRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hoverEvent:)]; @@ -740,6 +738,9 @@ static void SendFakeTouchEvent(FlutterEngine* engine, if (textInputPlugin != nil) { [self.keyboardManager addSecondaryResponder:textInputPlugin]; } + if ([_engine.get() viewController] == self) { + [textInputPlugin setupIndirectScribbleInteraction:self]; + } } - (void)removeInternalPlugins { diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 7de389b6e65..a2da6089aeb 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -144,6 +144,8 @@ typedef enum UIAccessibilityContrast : NSInteger { - (void)invalidateDisplayLink; - (void)addInternalPlugins; - (flutter::PointerData)generatePointerDataForFake; +- (void)sharedSetupWithProject:(nullable FlutterDartProject*)project + initialRoute:(nullable NSString*)initialRoute; @end @interface FlutterViewControllerTest : XCTestCase @@ -427,7 +429,22 @@ typedef enum UIAccessibilityContrast : NSInteger { mockEngine.viewController = viewController; UIView* view = viewController.view; XCTAssertNotNil(view); - OCMVerify([mockEngine attachView]); + OCMVerify(times(1), [mockEngine attachView]); +} + +- (void)testViewDidLoadDoesntInvokeEngineAttachViewWhenEngineNeedsLaunch { + FlutterEngine* mockEngine = OCMPartialMock([[FlutterEngine alloc] init]); + [mockEngine createShell:@"" libraryURI:@"" initialRoute:nil]; + mockEngine.viewController = nil; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:mockEngine + nibName:nil + bundle:nil]; + // sharedSetupWithProject sets the engine needs to be launched. + [viewController sharedSetupWithProject:nil initialRoute:nil]; + mockEngine.viewController = viewController; + UIView* view = viewController.view; + XCTAssertNotNil(view); + OCMVerify(never(), [mockEngine attachView]); } - (void)testInternalPluginsWeakPtrNotCrash { @@ -455,6 +472,11 @@ typedef enum UIAccessibilityContrast : NSInteger { FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:mockEngine nibName:nil bundle:nil]; + UIView* view = viewController.view; + // The implementation in viewDidLoad requires the viewControllers.viewLoaded is true. + // Accessing the view to make sure the view loads in the memory, + // which makes viewControllers.viewLoaded true. + XCTAssertNotNil(view); [viewController viewDidLoad]; OCMVerify([viewController addInternalPlugins]); }