From 344027bd52176e75ccb33e0e43a7b46b41a23436 Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Fri, 12 Mar 2021 14:17:47 -0800 Subject: [PATCH 1/3] fixes reference retaining issue in flutter text input plugin --- .../Source/FlutterTextInputPlugin.mm | 19 ++++++------- .../Source/FlutterTextInputPluginTest.m | 27 +++++++++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 9de83b2373972..9a54c84545822 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -1236,7 +1236,7 @@ @interface FlutterTextInputPlugin () // The current password-autofillable input fields that have yet to be saved. @property(nonatomic, readonly) NSMutableDictionary* autofillContext; -@property(nonatomic, assign) FlutterTextInputView* activeView; +@property(nonatomic, strong) FlutterTextInputView* activeView; @property(nonatomic, strong) FlutterTextInputViewAccessibilityHider* inputHider; @end @@ -1253,7 +1253,7 @@ - (instancetype)init { _reusableInputView = [[FlutterTextInputView alloc] init]; _reusableInputView.secureTextEntry = NO; _autofillContext = [[NSMutableDictionary alloc] init]; - _activeView = _reusableInputView; + _activeView = [_reusableInputView retain]; _inputHider = [[FlutterTextInputViewAccessibilityHider alloc] init]; } @@ -1263,6 +1263,7 @@ - (instancetype)init { - (void)dealloc { [self hideTextInput]; [_reusableInputView release]; + [_activeView release]; [_inputHider release]; [_autofillContext release]; [super dealloc]; @@ -1386,19 +1387,19 @@ - (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configur [self changeInputViewsAutofillVisibility:NO]; switch (autofillTypeOf(configuration)) { case FlutterAutofillTypeNone: - _activeView = [self updateAndShowReusableInputView:configuration]; + self.activeView = [self updateAndShowReusableInputView:configuration]; break; case FlutterAutofillTypeRegular: // If the group does not involve password autofill, only install the // input view that's being focused. - _activeView = [self updateAndShowAutofillViews:nil - focusedField:configuration - isPasswordRelated:NO]; + self.activeView = [self updateAndShowAutofillViews:nil + focusedField:configuration + isPasswordRelated:NO]; break; case FlutterAutofillTypePassword: - _activeView = [self updateAndShowAutofillViews:configuration[kAssociatedAutofillFields] - focusedField:configuration - isPasswordRelated:YES]; + self.activeView = [self updateAndShowAutofillViews:configuration[kAssociatedAutofillFields] + focusedField:configuration + isPasswordRelated:YES]; break; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m index 4cbe318f791e1..e4b6879130a4e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m @@ -865,4 +865,31 @@ - (void)testFlutterTokenizerCanParseLines { XCTAssertEqual(range.range.length, 20u); } +- (void)testFlutterTextInputPluginRetainsFlutterTextInputView { + FlutterTextInputPlugin* myInputPlugin; + id myEngine = OCMClassMock([FlutterEngine class]); + myInputPlugin = [[FlutterTextInputPlugin alloc] init]; + myInputPlugin.textInputDelegate = myEngine; + __weak UIView* activeView; + @autoreleasepool { + FlutterMethodCall* setClientCall = [FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + [NSNumber numberWithInt:123], self.mutablePasswordTemplateCopy + ]]; + [myInputPlugin handleMethodCall:setClientCall + result:^(id _Nullable result){ + }]; + activeView = myInputPlugin.textInputView; + FlutterMethodCall* hideCall = [FlutterMethodCall methodCallWithMethodName:@"TextInput.hide" + arguments:@[]]; + [myInputPlugin handleMethodCall:hideCall + result:^(id _Nullable result){ + }]; + XCTAssertNotNil(activeView); + } + // This assert proves we released the old active view. + XCTAssertNotNil(activeView); +} + @end From f55a3953abdd1487c3ba0b3e8020613e8dc4ffae Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Fri, 12 Mar 2021 14:31:06 -0800 Subject: [PATCH 2/3] update comment --- .../darwin/ios/framework/Source/FlutterTextInputPluginTest.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m index e4b6879130a4e..62cf43bdeb1bd 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m @@ -888,7 +888,7 @@ - (void)testFlutterTextInputPluginRetainsFlutterTextInputView { }]; XCTAssertNotNil(activeView); } - // This assert proves we released the old active view. + // This assert proves the myInputPlugin.textInputView is not gc'd. XCTAssertNotNil(activeView); } From 4f47e6e1f59c84cb98e032ed610333f49f9aafc3 Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Mon, 15 Mar 2021 13:25:18 -0700 Subject: [PATCH 3/3] addressing comment --- .../darwin/ios/framework/Source/FlutterTextInputPluginTest.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m index 62cf43bdeb1bd..4b0a0d4ce91cd 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m @@ -888,7 +888,7 @@ - (void)testFlutterTextInputPluginRetainsFlutterTextInputView { }]; XCTAssertNotNil(activeView); } - // This assert proves the myInputPlugin.textInputView is not gc'd. + // This assert proves the myInputPlugin.textInputView is not deallocated. XCTAssertNotNil(activeView); }