@@ -110,7 +110,21 @@ - (void)setTextAlignment:(NSTextAlignment)textAlignment
110
110
111
111
- (void )setAttributedText : (NSAttributedString *)attributedText
112
112
{
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
+
114
128
[self textDidChange ];
115
129
}
116
130
@@ -241,4 +255,20 @@ - (void)invalidatePlaceholderVisibility
241
255
_placeholderView.hidden = !isVisible;
242
256
}
243
257
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
+
244
274
@end
0 commit comments