Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,7 @@ @interface FlutterTextInputPlugin ()
// The current password-autofillable input fields that have yet to be saved.
@property(nonatomic, readonly)
NSMutableDictionary<NSString*, FlutterTextInputView*>* autofillContext;
@property(nonatomic, assign) FlutterTextInputView* activeView;
@property(nonatomic, strong) FlutterTextInputView* activeView;
@property(nonatomic, strong) FlutterTextInputViewAccessibilityHider* inputHider;
@end

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

Expand All @@ -1263,6 +1263,7 @@ - (instancetype)init {
- (void)dealloc {
[self hideTextInput];
[_reusableInputView release];
[_activeView release];
[_inputHider release];
[_autofillContext release];
[super dealloc];
Expand Down Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 the myInputPlugin.textInputView is not deallocated.
XCTAssertNotNil(activeView);
}

@end