@@ -110,7 +110,21 @@ - (void)setTextAlignment:(NSTextAlignment)textAlignment
110110
111111- (void )setAttributedText : (NSAttributedString *)attributedText
112112{
113- [super setAttributedText: attributedText];
113+ // Using `setAttributedString:` while user is typing breaks some internal mechanics
114+ // when entering complex input languages such as Chinese, Korean or Japanese.
115+ // see: https://github.com/facebook/react-native/issues/19339
116+
117+ // We try to avoid calling this method as much as we can.
118+ // If the text has changed, there is nothing we can do.
119+ if (![super .attributedText.string isEqualToString: attributedText.string]) {
120+ [super setAttributedText: attributedText];
121+ } else {
122+ // But if the text is preserved, we just copying the attributes from the source string.
123+ if (![super .attributedText isEqualToAttributedString: attributedText]) {
124+ [self copyTextAttributesFrom: attributedText];
125+ }
126+ }
127+
114128 [self textDidChange ];
115129}
116130
@@ -241,4 +255,20 @@ - (void)invalidatePlaceholderVisibility
241255 _placeholderView.hidden = !isVisible;
242256}
243257
258+ #pragma mark - Utility Methods
259+
260+ - (void )copyTextAttributesFrom : (NSAttributedString *)sourceString
261+ {
262+ [self .textStorage beginEditing ];
263+
264+ NSTextStorage *textStorage = self.textStorage ;
265+ [sourceString enumerateAttributesInRange: NSMakeRange (0 , sourceString.length)
266+ options: NSAttributedStringEnumerationReverse
267+ usingBlock: ^(NSDictionary <NSAttributedStringKey ,id > * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
268+ [textStorage setAttributes: attrs range: range];
269+ }];
270+
271+ [self .textStorage endEditing ];
272+ }
273+
244274@end
0 commit comments