diff --git a/node_modules/react-native-uitextview/ios/RNUITextView.mm b/node_modules/react-native-uitextview/ios/RNUITextView.mm index d0c31ed..df8a233 100644 --- a/node_modules/react-native-uitextview/ios/RNUITextView.mm +++ b/node_modules/react-native-uitextview/ios/RNUITextView.mm @@ -22,6 +22,7 @@ using namespace facebook::react; RNUITextViewShadowNode::ConcreteState::Shared _state; UITapGestureRecognizer * _outsideTapRecognizer; BOOL _suppressSelectionChange; + CGRect _lastTextLayoutFrame; } + (ComponentDescriptorProvider)componentDescriptorProvider @@ -47,7 +48,8 @@ using namespace facebook::react; _textView.delegate = self; // Must match RCTTextLayoutManager, which measures with usesFontLeading = NO. _textView.layoutManager.usesFontLeading = NO; - [self addSubview:_textView]; + _textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [_view addSubview:_textView]; const auto longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressIfNecessary:)]; @@ -94,16 +96,15 @@ using namespace facebook::react; // Reset the frame to zero so that when it properly lays out on the next use _textView.frame = CGRectZero; _textView.attributedText = nil; + _lastTextLayoutFrame = CGRectZero; } - (void)layoutSubviews { [super layoutSubviews]; - // _textView's frame is assigned inside drawRect, which only fires when - // state changes. Trigger a redraw whenever the host frame moves out from - // under it (rotation, parent relayout) so the text view resizes and - // onTextLayout re-fires with the new line wrapping. - if (!CGRectEqualToRect(_textView.frame, _view.frame)) { + // Autoresizing updates UIKit immediately; report the new line layout when + // the content container's bounds change. + if (!CGRectEqualToRect(_lastTextLayoutFrame, _view.bounds)) { [self setNeedsDisplay]; } } @@ -124,8 +125,9 @@ using namespace facebook::react; // entirely when nothing actually changed so a JS-side state update made in // response to onSelectionChange doesn't deselect what the user is selecting. const BOOL textChanged = ![_textView.attributedText isEqualToAttributedString:convertedAttrString]; - const BOOL frameChanged = !CGRectEqualToRect(_textView.frame, _view.frame); - if (!textChanged && !frameChanged) { + const BOOL frameChanged = !CGRectEqualToRect(_textView.frame, _view.bounds); + const BOOL layoutChanged = !CGRectEqualToRect(_lastTextLayoutFrame, _view.bounds); + if (!textChanged && !frameChanged && !layoutChanged) { return; } if (textChanged) { @@ -142,7 +144,7 @@ using namespace facebook::react; _suppressSelectionChange = NO; } if (frameChanged) { - _textView.frame = _view.frame; + _textView.frame = _view.bounds; } __block std::vector lines; @@ -162,6 +164,7 @@ using namespace facebook::react; } }]; + _lastTextLayoutFrame = _view.bounds; if (_eventEmitter != nullptr) { std::dynamic_pointer_cast(_eventEmitter) ->onTextLayout(facebook::react::RNUITextViewEventEmitter::OnTextLayout{static_cast(self.tag), lines});