iOS: Avoid attaching view twice when loading view in FlutterViewController (flutter/engine#34642)

This commit is contained in:
Chris Yang 2022-07-14 11:30:04 -07:00 committed by GitHub
parent 27f178ca60
commit da5e08bbae
3 changed files with 28 additions and 6 deletions

View File

@ -393,7 +393,6 @@ static constexpr int kNumProfilerSamplesPerSec = 5;
- (void)attachView {
self.iosPlatformView->attachView();
[_textInputPlugin.get() setupIndirectScribbleInteraction:self.viewController];
}
- (void)setFlutterViewControllerWillDeallocObserver:(id<NSObject>)observer {

View File

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

View File

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