Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,35 @@ - (void)textDidChange
{
_textWasPasted = NO;
[self _invalidatePlaceholderVisibility];
[self _relayoutFirstTextLayoutFragmentIfMisplaced];
}

// On iOS 27, TextKit 2 can leave the first layout fragment pushed down by its own height (origin.y == height) after
// an edit that replaces text inside the first paragraph while later paragraphs exist, e.g. Korean syllable
// recomposition in a non-scrolling text view. UIKit hides this when Auto Layout re-measures the view, but views
// here are sized with frames, so the whole text stays shifted until the next edit (FB25281535).
// Re-laying out just that fragment fixes it. Nothing is done while the fragment is in place.
- (void)_relayoutFirstTextLayoutFragmentIfMisplaced
{
if (@available(iOS 16.0, tvOS 16.0, *)) {
NSTextLayoutManager *textLayoutManager = self.textLayoutManager;
if (textLayoutManager == nil) {
return;
}
__block NSTextLayoutFragment *firstFragment = nil;
[textLayoutManager enumerateTextLayoutFragmentsFromLocation:textLayoutManager.documentRange.location
options:NSTextLayoutFragmentEnumerationOptionsNone
usingBlock:^BOOL(NSTextLayoutFragment *fragment) {
firstFragment = fragment;
return NO;
}];
if (firstFragment == nil || firstFragment.layoutFragmentFrame.origin.y <= 0) {
return;
}
NSTextRange *range = firstFragment.rangeInElement;
[textLayoutManager invalidateLayoutForRange:range];
[textLayoutManager ensureLayoutForRange:range];
}
}

- (void)setDisableKeyboardShortcuts:(BOOL)disableKeyboardShortcuts
Expand Down
Loading