Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 04b0451

Browse files
authored
fixes reference retaining issue in flutter text input plugin (#24768)
1 parent aa83691 commit 04b0451

2 files changed

Lines changed: 37 additions & 9 deletions

File tree

shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,7 +1236,7 @@ @interface FlutterTextInputPlugin ()
12361236
// The current password-autofillable input fields that have yet to be saved.
12371237
@property(nonatomic, readonly)
12381238
NSMutableDictionary<NSString*, FlutterTextInputView*>* autofillContext;
1239-
@property(nonatomic, assign) FlutterTextInputView* activeView;
1239+
@property(nonatomic, strong) FlutterTextInputView* activeView;
12401240
@property(nonatomic, strong) FlutterTextInputViewAccessibilityHider* inputHider;
12411241
@end
12421242

@@ -1253,7 +1253,7 @@ - (instancetype)init {
12531253
_reusableInputView = [[FlutterTextInputView alloc] init];
12541254
_reusableInputView.secureTextEntry = NO;
12551255
_autofillContext = [[NSMutableDictionary alloc] init];
1256-
_activeView = _reusableInputView;
1256+
_activeView = [_reusableInputView retain];
12571257
_inputHider = [[FlutterTextInputViewAccessibilityHider alloc] init];
12581258
}
12591259

@@ -1263,6 +1263,7 @@ - (instancetype)init {
12631263
- (void)dealloc {
12641264
[self hideTextInput];
12651265
[_reusableInputView release];
1266+
[_activeView release];
12661267
[_inputHider release];
12671268
[_autofillContext release];
12681269
[super dealloc];
@@ -1386,19 +1387,19 @@ - (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configur
13861387
[self changeInputViewsAutofillVisibility:NO];
13871388
switch (autofillTypeOf(configuration)) {
13881389
case FlutterAutofillTypeNone:
1389-
_activeView = [self updateAndShowReusableInputView:configuration];
1390+
self.activeView = [self updateAndShowReusableInputView:configuration];
13901391
break;
13911392
case FlutterAutofillTypeRegular:
13921393
// If the group does not involve password autofill, only install the
13931394
// input view that's being focused.
1394-
_activeView = [self updateAndShowAutofillViews:nil
1395-
focusedField:configuration
1396-
isPasswordRelated:NO];
1395+
self.activeView = [self updateAndShowAutofillViews:nil
1396+
focusedField:configuration
1397+
isPasswordRelated:NO];
13971398
break;
13981399
case FlutterAutofillTypePassword:
1399-
_activeView = [self updateAndShowAutofillViews:configuration[kAssociatedAutofillFields]
1400-
focusedField:configuration
1401-
isPasswordRelated:YES];
1400+
self.activeView = [self updateAndShowAutofillViews:configuration[kAssociatedAutofillFields]
1401+
focusedField:configuration
1402+
isPasswordRelated:YES];
14021403
break;
14031404
}
14041405

shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,4 +865,31 @@ - (void)testFlutterTokenizerCanParseLines {
865865
XCTAssertEqual(range.range.length, 20u);
866866
}
867867

868+
- (void)testFlutterTextInputPluginRetainsFlutterTextInputView {
869+
FlutterTextInputPlugin* myInputPlugin;
870+
id myEngine = OCMClassMock([FlutterEngine class]);
871+
myInputPlugin = [[FlutterTextInputPlugin alloc] init];
872+
myInputPlugin.textInputDelegate = myEngine;
873+
__weak UIView* activeView;
874+
@autoreleasepool {
875+
FlutterMethodCall* setClientCall = [FlutterMethodCall
876+
methodCallWithMethodName:@"TextInput.setClient"
877+
arguments:@[
878+
[NSNumber numberWithInt:123], self.mutablePasswordTemplateCopy
879+
]];
880+
[myInputPlugin handleMethodCall:setClientCall
881+
result:^(id _Nullable result){
882+
}];
883+
activeView = myInputPlugin.textInputView;
884+
FlutterMethodCall* hideCall = [FlutterMethodCall methodCallWithMethodName:@"TextInput.hide"
885+
arguments:@[]];
886+
[myInputPlugin handleMethodCall:hideCall
887+
result:^(id _Nullable result){
888+
}];
889+
XCTAssertNotNil(activeView);
890+
}
891+
// This assert proves the myInputPlugin.textInputView is not deallocated.
892+
XCTAssertNotNil(activeView);
893+
}
894+
868895
@end

0 commit comments

Comments
 (0)