steipete / PSPDFTextView

A subclass of UITextView that fixes the most glaring problems from iOS 7 and 7.1.
http://pspdfkit.com
MIT License
873 stars 73 forks source link

Wrong offset with newlines #12

Open hpique opened 10 years ago

hpique commented 10 years ago

The textView scrolls to the wrong offset when reaching the end of texts with newlines. The problem appears to be carectRectForPosition:, which reports the wrong rect for the end of document. See log and animated gif below.

Steps to reproduce:

  1. Use text: @"1\n2\n3\n4\n5\n6\n7\n8\n9\n10"
  2. Run example.
  3. Position cursor at the end. Type Intro. This will already cause a quick glitch.
  4. Move scroll up.
  5. Move scroll down. The offset will be wrong.

bug

Log:

textViewDidChangeSelection
scrollToVisibleCaretAnimated:1
position: <_UITextKitTextPosition: 0x8b7d760> (20F)
caretRect: {{25.920013, 44.860001}, {2, 25.359999}}
scrollToVisibleCaretAnimated:0
position: <_UITextKitTextPosition: 0x8b7d760> (20F)
caretRect: {{25.920013, 221.73999}, {2, 25.359999}}
shouldChangeTextInRange
ensureCaretIsVisibleWithReplacementText
scheduleScrollToVisibleCaretWithDelay
textViewDidChangeSelection
scrollToVisibleCaretAnimated:1
position: <_UITextKitTextPosition: 0x8d68c50> (21F)
caretRect: {{4, 245.59999}, {2, 25.359999}}
textViewDidChange
scrollToVisibleCaretAnimated:0
position: <_UITextKitTextPosition: 0x8d68c50> (21F)
caretRect: {{4, 245.59999}, {2, 25.359999}}
scrollToVisibleCaret
scrollToVisibleCaretAnimated:0
position: <_UITextKitTextPosition: 0x8d68c50> (21F)
caretRect: {{4, 245.59999}, {2, 25.359999}}
textViewDidChangeSelection
scrollToVisibleCaretAnimated:1
position: <_UITextKitTextPosition: 0x8c2d390> (18F)
caretRect: {{4, 221.73999}, {2, 25.359999}}
textViewDidChangeSelection
scrollToVisibleCaretAnimated:1
position: <_UITextKitTextPosition: 0x8d837d0> (21F)
caretRect: {{4, 54.719997}, {2, 25.359999}}
hpique commented 10 years ago

I have no idea why the above happens but this could be a possible workaround:

- (void)scrollToVisibleCaretAnimated:(BOOL)animated {
    UITextPosition *selectedTextRangeEnd = self.selectedTextRange.end;
    CGRect rect = [self caretRectForPosition:selectedTextRangeEnd];
    UITextPosition *givenCaretPosition = [self closestPositionToPoint:CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect))];
    if ([self comparePosition:givenCaretPosition toPosition:selectedTextRangeEnd] == NSOrderedSame)
    {
        [self scrollRectToVisibleConsideringInsets:rect animated:animated];
    }
}
mythodeia commented 9 years ago

:+1: that solved my issue as well

joshuafeldman commented 8 years ago

I am seeing this issue as well. When a newline is added (with a character or a line break character) the caret is not always properly scrolled into view. A lot of the time the last line is cut off. The above does fix the issue but now the text jumps around when the frame is equal to the height of the text.

joshuafeldman commented 8 years ago

I can fix the text jumping by changing

contentOffset.y = CGRectGetMinY(rect) - insets.top;

to

contentOffset.y = MAX(CGRectGetMinY(rect) - insets.top, 0);

in scrollRectToVisibleConsideringInsets:animated:

mythodeia commented 8 years ago

@joshuafeldman thanks for sharing :+1: