diff --git a/apple/MarkdownTextFieldObserver.mm b/apple/MarkdownTextFieldObserver.mm index dff905b4..d0f94bd8 100644 --- a/apple/MarkdownTextFieldObserver.mm +++ b/apple/MarkdownTextFieldObserver.mm @@ -23,21 +23,42 @@ - (instancetype)initWithTextField:(nonnull RCTUITextField *)textField markdownUt - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (_active && ([keyPath isEqualToString:@"text"] || [keyPath isEqualToString:@"attributedText"])) { - [self textFieldDidChange:_textField]; + [self applyMarkdownFormatting]; } } -- (void)textFieldDidChange:(__unused UITextField *)textField { +- (void)textFieldDidChange:(__unused UITextField *)textField +{ + [self applyMarkdownFormatting]; +} + +- (void)textFieldDidEndEditing:(__unused UITextField *)textField +{ + // In order to prevent iOS from applying underline to the whole text if text ends with a link on blur, + // we need to update `defaultTextAttributes` which at this point doesn't contain NSUnderline attribute yet. + // It seems like the setter performs deep comparision, so we differentiate the new value using a counter, + // otherwise this trick would work only once. + static NSAttributedStringKey RCTLiveMarkdownForceUpdateAttributeName = @"RCTLiveMarkdownForceUpdate"; + static NSUInteger counter = 0; + NSMutableDictionary *defaultTextAttributes = [_textField.defaultTextAttributes mutableCopy]; + defaultTextAttributes[RCTLiveMarkdownForceUpdateAttributeName] = @(counter++); + _textField.defaultTextAttributes = defaultTextAttributes; + [self applyMarkdownFormatting]; +} + +- (void)applyMarkdownFormatting +{ react_native_assert(_textField.defaultTextAttributes != nil); if (_textField.markedTextRange != nil) { return; // skip formatting during multi-stage input to avoid breaking internal state } - NSMutableAttributedString *attributedText = [textField.attributedText mutableCopy]; + NSMutableAttributedString *attributedText = [_textField.attributedText mutableCopy]; [_markdownUtils applyMarkdownFormatting:attributedText withDefaultTextAttributes:_textField.defaultTextAttributes]; UITextRange *textRange = _textField.selectedTextRange; + _active = NO; // prevent recursion _textField.attributedText = attributedText; _active = YES; @@ -49,18 +70,4 @@ - (void)textFieldDidChange:(__unused UITextField *)textField { _textField.typingAttributes = _textField.defaultTextAttributes; } -- (void)textFieldDidEndEditing:(__unused UITextField *)textField -{ - // In order to prevent iOS from applying underline to the whole text if text ends with a link on blur, - // we need to update `defaultTextAttributes` which at this point doesn't contain NSUnderline attribute yet. - // It seems like the setter performs deep comparision, so we differentiate the new value using a counter, - // otherwise this trick would work only once. - static NSAttributedStringKey RCTLiveMarkdownForceUpdateAttributeName = @"RCTLiveMarkdownForceUpdate"; - static NSUInteger counter = 0; - NSMutableDictionary *defaultTextAttributes = [_textField.defaultTextAttributes mutableCopy]; - defaultTextAttributes[RCTLiveMarkdownForceUpdateAttributeName] = @(counter++); - _textField.defaultTextAttributes = defaultTextAttributes; - [self textFieldDidChange:_textField]; -} - @end