diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.h b/Libraries/Text/TextInput/RCTBaseTextInputView.h index 4acb4147ae6..fb5f02ec5ad 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.h +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.h @@ -40,6 +40,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, nullable) RCTDirectEventBlock onScroll; @property (nonatomic, assign) NSInteger mostRecentEventCount; +@property (nonatomic, assign, readonly) NSInteger nativeEventCount; @property (nonatomic, assign) BOOL autoFocus; @property (nonatomic, assign) BOOL blurOnSubmit; @property (nonatomic, assign) BOOL selectTextOnFocus; @@ -51,9 +52,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) NSString *inputAccessoryViewID; @property (nonatomic, assign) UIKeyboardType keyboardType; -- (void)setText:(NSString *__nullable)text - selectionStart:(NSInteger)start - selectionEnd:(NSInteger)end; +/** + Sets selection intext input if both start and end are within range of the text input. + **/ +- (void)setSelectionStart:(NSInteger)start + selectionEnd:(NSInteger)end; @end diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.m b/Libraries/Text/TextInput/RCTBaseTextInputView.m index 538832e0e92..aa69593f68f 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -24,7 +24,6 @@ __weak RCTEventDispatcher *_eventDispatcher; BOOL _hasInputAccesoryView; NSString *_Nullable _predictedText; - NSInteger _nativeEventCount; BOOL _didMoveToWindow; } @@ -199,17 +198,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame) } } -- (void)setText:(NSString *__nullable)text - selectionStart:(NSInteger)start - selectionEnd:(NSInteger)end +- (void)setSelectionStart:(NSInteger)start + selectionEnd:(NSInteger)end { - if (text) { - NSMutableAttributedString *mutableString = - [[NSMutableAttributedString alloc] initWithAttributedString:self.backedTextInputView.attributedText]; - [mutableString replaceCharactersInRange:NSMakeRange(0, mutableString.string.length) withString:text]; - self.backedTextInputView.attributedText = mutableString; - } - UITextPosition *startPosition = [self.backedTextInputView positionFromPosition:self.backedTextInputView.beginningOfDocument offset:start]; UITextPosition *endPosition = [self.backedTextInputView positionFromPosition:self.backedTextInputView.beginningOfDocument diff --git a/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m b/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m index d0626ee1f4b..dca143760a1 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputViewManager.m @@ -125,8 +125,18 @@ RCT_EXPORT_METHOD(setTextAndSelection : (nonnull NSNumber *)viewTag { [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { RCTBaseTextInputView *view = (RCTBaseTextInputView *)viewRegistry[viewTag]; - view.mostRecentEventCount = mostRecentEventCount; - [view setText:value selectionStart:start selectionEnd:end]; + NSInteger eventLag = view.nativeEventCount - mostRecentEventCount; + if (eventLag != 0) { + return; + } + RCTExecuteOnUIManagerQueue(^{ + RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[self.bridge.uiManager shadowViewForReactTag:viewTag]; + [shadowView setText:value]; + [self.bridge.uiManager setNeedsLayout]; + RCTExecuteOnMainQueue(^{ + [view setSelectionStart:start selectionEnd:end]; + }); + }); }]; } diff --git a/RNTester/js/examples/TextInput/TextInputSharedExamples.js b/RNTester/js/examples/TextInput/TextInputSharedExamples.js index 3ca4b958e06..629991164f9 100644 --- a/RNTester/js/examples/TextInput/TextInputSharedExamples.js +++ b/RNTester/js/examples/TextInput/TextInputSharedExamples.js @@ -161,9 +161,9 @@ class RewriteInvalidCharactersAndClearExample extends React.Component< ref={ref => { this.inputRef = ref; }} - multiline={false} + multiline={true} onChangeText={text => { - this.setState({text: text.replace(/\s/g, '')}); + this.setState({text: text.replace(/ /g, '')}); }} style={styles.default} value={this.state.text}