From 64475aeb3b1b0e37bdad2c2d5abb2116b2141c06 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 14 Dec 2022 09:17:54 -0800 Subject: [PATCH] Switch order of onSelectionChange and onChange events on iOS (#35603) Summary: Switched order of onSelectionChange and onChange events on iOS This was already fixed but for fabric only https://github.com/facebook/react-native/blob/main/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm#L36-L46 This PR is a complementary of https://github.com/facebook/react-native/commit/7b4889937ceb0eccdbb62a610b58525c29928be7 Fixes https://github.com/facebook/react-native/issues/28865 ## Changelog [IOS] [FIXED] - onSelectionChange() is fired before onChange() on multiline TextInput Pull Request resolved: https://github.com/facebook/react-native/pull/35603 Test Plan: Reproduce the minimal example provided here https://github.com/facebook/react-native/issues/28865 Verify that the events order is onChange then onSelectionChange with no duplicates Reviewed By: cipolleschi Differential Revision: D41947673 Pulled By: dmytrorykun fbshipit-source-id: cf452a6101400b1b54295c83fa7735449d91e781 --- .../TextInput/RCTBackedTextInputDelegateAdapter.m | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m b/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m index 7722f831ad0837..0542362dbe0ac6 100644 --- a/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m +++ b/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m @@ -168,6 +168,8 @@ @interface RCTBackedTextViewDelegateAdapter () @implementation RCTBackedTextViewDelegateAdapter { __weak UITextView *_backedTextInputView; + NSAttributedString *_lastStringStateWasUpdatedWith; + BOOL _ignoreNextTextInputCall; BOOL _textDidChangeIsComing; UITextRange *_previousSelectedTextRange; } @@ -254,12 +256,21 @@ - (BOOL)textView:(__unused UITextView *)textView shouldChangeTextInRange:(NSRang - (void)textViewDidChange:(__unused UITextView *)textView { + if (_ignoreNextTextInputCall && [_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) { + _ignoreNextTextInputCall = NO; + return; + } + _lastStringStateWasUpdatedWith = _backedTextInputView.attributedText; _textDidChangeIsComing = NO; [_backedTextInputView.textInputDelegate textInputDidChange]; } - (void)textViewDidChangeSelection:(__unused UITextView *)textView { + if (![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) { + [self textViewDidChange:_backedTextInputView]; + _ignoreNextTextInputCall = YES; + } [self textViewProbablyDidChangeSelection]; }