From 819a40bc227f7bc9e329903e35c4bcab5bbb5924 Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Wed, 17 May 2017 19:36:27 -0700 Subject: [PATCH] Smarter text/selection will/didChange events (flutter/engine#3699) Check incoming text editing state and only fire textWillChange:, textDidChange:, selectionWillChange:, selectionDidChange: when the text or selection actually changes. On selectionWillChange: in a text field where auto-correct is enabled, iOS will attempt to auto-correct the word preceding the cursor. This change also updates the text before calling selectionWillChange: to prevent auto-correction on the preceding value of the text field. --- .../Source/FlutterTextInputPlugin.mm | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 775b5c3cdd6..4199bafa6d7 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -162,25 +162,32 @@ static UIKeyboardType ToUIKeyboardType(NSString* inputType) { } - (void)setTextInputState:(NSDictionary*)state { - [self.inputDelegate selectionWillChange:self]; - [self.inputDelegate textWillChange:self]; - - [self.text setString:state[@"text"]]; + NSString* newText = state[@"text"]; + BOOL textChanged = ![self.text isEqualToString:newText]; + if (textChanged) { + [self.inputDelegate textWillChange:self]; + [self.text setString:newText]; + } NSInteger selectionBase = [state[@"selectionBase"] intValue]; NSInteger selectionExtent = [state[@"selectionExtent"] intValue]; NSUInteger start = MIN(MAX(0, MIN(selectionBase, selectionExtent)), (NSInteger)self.text.length); NSUInteger end = MIN(MAX(0, MAX(selectionBase, selectionExtent)), (NSInteger)self.text.length); NSRange selectedRange = NSMakeRange(start, end - start); - [self setSelectedTextRange:[FlutterTextRange rangeWithNSRange:selectedRange] - updateEditingState:NO]; + NSRange oldSelectedRange = [(FlutterTextRange*)self.selectedTextRange range]; + if (selectedRange.location != oldSelectedRange.location || + selectedRange.length != oldSelectedRange.length) { + [self.inputDelegate selectionWillChange:self]; + [self setSelectedTextRange:[FlutterTextRange rangeWithNSRange:selectedRange] + updateEditingState:NO]; + _selectionAffinity = _kTextAffinityDownstream; + if ([state[@"selectionAffinity"] isEqualToString:@(_kTextAffinityUpstream)]) + _selectionAffinity = _kTextAffinityUpstream; + [self.inputDelegate selectionDidChange:self]; + } - _selectionAffinity = _kTextAffinityDownstream; - if ([state[@"selectionAffinity"] isEqualToString:@(_kTextAffinityUpstream)]) - _selectionAffinity = _kTextAffinityUpstream; - - [self.inputDelegate selectionDidChange:self]; - [self.inputDelegate textDidChange:self]; + if (textChanged) + [self.inputDelegate textDidChange:self]; } #pragma mark - UIResponder Overrides