From 7feafefa777501270191f357a4d56daa56648862 Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Tue, 21 Feb 2023 14:12:41 +0800 Subject: [PATCH 1/3] [iOS] Avoid handle method calls when host UIViewController.view is nil. --- .../ios/framework/Source/FlutterTextInputPlugin.mm | 5 +++++ .../framework/Source/FlutterTextInputPluginTest.mm | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 68b57ae22f68f..85131f5c86a1a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -2081,6 +2081,11 @@ - (void)removeEnableFlutterTextInputViewAccessibilityTimer { } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + if (_viewController.view == nil) { + result(nil); + return; + } + NSString* method = call.method; id args = call.arguments; if ([method isEqualToString:kShowMethod]) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm index 459a74335bcfa..2cb8a79800aac 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm @@ -166,6 +166,20 @@ - (FlutterTextRange*)getLineRangeFromTokenizer:(id)tokeniz #pragma mark - Tests +- (void)testTextInputPluginWillNotHandleMethodWhenViewControllerIsNil { + FlutterEngine* flutterEngine = [[FlutterEngine alloc] init]; + FlutterTextInputPlugin* inputPlugin = + [[FlutterTextInputPlugin alloc] initWithDelegate:(id)flutterEngine]; + XCTAssertNil(inputPlugin.viewController); + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"TextInput.show" + arguments:nil]; + [inputPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + + }]; + XCTAssertNil(inputPlugin.activeView); +} + - (void)testInvokeStartLiveTextInput { FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"TextInput.startLiveTextInput" arguments:nil]; From 858cdfb4ea92f692524a84205fbeb331e2d724eb Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Tue, 21 Feb 2023 15:41:33 +0800 Subject: [PATCH 2/3] Modify code. --- .../darwin/ios/framework/Source/FlutterTextInputPlugin.mm | 3 +++ .../ios/framework/Source/FlutterTextInputPluginTest.mm | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 85131f5c86a1a..80830548bc161 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -2082,6 +2082,9 @@ - (void)removeEnableFlutterTextInputViewAccessibilityTimer { - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if (_viewController.view == nil) { + // If UIViewController's view has been detached, we ignore incoming method call + // to avoid crash. + // See https://github.com/flutter/flutter/issues/106404. result(nil); return; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm index 2cb8a79800aac..66bbea9e46d4b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm @@ -173,11 +173,15 @@ - (void)testTextInputPluginWillNotHandleMethodWhenViewControllerIsNil { XCTAssertNil(inputPlugin.viewController); FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"TextInput.show" arguments:nil]; - [inputPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ + XCTestExpectation* expectation = [[XCTestExpectation alloc] initWithDescription:@"result called"]; + [inputPlugin handleMethodCall:methodCall + result:^(id _Nullable result) { + XCTAssertNil(result); + [expectation fulfill]; }]; XCTAssertNil(inputPlugin.activeView); + [self waitForExpectations:@[ expectation ] timeout:1.0]; } - (void)testInvokeStartLiveTextInput { From f3d71cb526421c219d0d750a044fb00acebc0b7e Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Wed, 22 Feb 2023 11:47:06 +0800 Subject: [PATCH 3/3] ++ --- .../framework/Source/FlutterTextInputPlugin.mm | 15 +++++++-------- .../Source/FlutterTextInputPluginTest.mm | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 80830548bc161..1ac316e819ab4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -2081,14 +2081,6 @@ - (void)removeEnableFlutterTextInputViewAccessibilityTimer { } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if (_viewController.view == nil) { - // If UIViewController's view has been detached, we ignore incoming method call - // to avoid crash. - // See https://github.com/flutter/flutter/issues/106404. - result(nil); - return; - } - NSString* method = call.method; id args = call.arguments; if ([method isEqualToString:kShowMethod]) { @@ -2448,6 +2440,13 @@ - (void)addToInputParentViewIfNeeded:(FlutterTextInputView*)inputView { if (![inputView isDescendantOfView:_inputHider]) { [_inputHider addSubview:inputView]; } + + if (_viewController.view == nil) { + // If view controller's view has detached from flutter engine, we don't add _inputHider + // in parent view to fallback and avoid crash. + // https://github.com/flutter/flutter/issues/106404. + return; + } UIView* parentView = self.hostView; if (_inputHider.superview != parentView) { [parentView addSubview:_inputHider]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm index 66bbea9e46d4b..84827c4722e87 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm @@ -166,7 +166,7 @@ - (FlutterTextRange*)getLineRangeFromTokenizer:(id)tokeniz #pragma mark - Tests -- (void)testTextInputPluginWillNotHandleMethodWhenViewControllerIsNil { +- (void)testWillNotCrashWhenViewControllerIsNil { FlutterEngine* flutterEngine = [[FlutterEngine alloc] init]; FlutterTextInputPlugin* inputPlugin = [[FlutterTextInputPlugin alloc] initWithDelegate:(id)flutterEngine];