I have a UITextView. It reads its text string and parses the markdown and displays it on screen using NSAttributedString
from AttributedString
.
The Problem
When the text is short, it's all good. But when the text is long beyond maybe 2 screen height, it starts to jump up and down. It jumps up on newLine, then down on another newLine, then up on the 3rd newLine, then down on 4th, and repeat.
Another problem is that it messes up my draw(in:rect)
method in UITextView
subclass that draws gray background rectangles for quote and code blocks. The drawing is based on some individual character locations. So I guess the character locations are also messed up when the UITextView
tries to calculate and layout its attributedText
.
Some Implementation Details
- parsing is done in a separate package.
- I used parsed detail to construct a new attributedString
- I implemented
textViewDidChange(_ textView: UITextView)
so that it updates theattributedText
upon any new characters input or deletion. - Because changing
attributedText
so often will always bring the typing cursor to the end of the textView, I track the cursor location before applying the attributes, then give it back to textView so that textView can stay where it was.
func textViewDidChange(_ textView: UITextView) {
let cursor = textView.selectedRange
// the problem will be gone if I comment out applyAttributes()
applyAttributes()
textView.selectedRange = cursor
textView.scrollRangeToVisible(cursor)
}
private func applyAttributes() {
// 1. get parsed tokens
// 2. construct attributedString using the tokens
// 3. give the token to textView.attributedText
// 4. draw textView's rect based on displayed attributedText
}
When I remove step 4, the problem persists.
The problem occurs for both software and hardware keyboards
Any tips on how I can improve my code, my habit, and my form are also appreciated.
Thanks in advance.