-
-
Save danielgomezrico/75a9a02cb27f02c4b35f to your computer and use it in GitHub Desktop.
import UIKit | |
extension UITextView { | |
func scrollToBotom() { | |
let range = NSMakeRange(text.characters.count - 1, 1); | |
scrollRangeToVisible(range); | |
} | |
} |
This is both slow with a lot of text (the .count property accessor is O(n) for collections which do not conform to SequenceType, and you will see very noticeable slowdowns once you get to 100,000+ characters), and doesn't work properly with things like emoji.
Here's why: scrollRangeToVisible expects an NSRange over the content of the NSTextStorage object, which is an NSAttributedString and stores its actual text content as an NSString, which is indexed by UTF-16 code units. A Swift String's .characters member, on the other hand, presents the String's content as a collection of Unicode extended grapheme clusters (which correspond to visible characters a.k.a. glyphs).
In cases where there is not a one-to-one mapping between UTF-16 code units and extended grapheme clusters (such as with emoji, which generally require two UTF-16 code units to represent — see https://www.objc.io/issues/9-strings/unicode/ for a good discussion), .characters.count of String will report a very different value than .length of NSString.
Fortunately, there is a simple modification which solves both problems (speed and full Unicode compatibility). Just replace this line:
let range = NSMakeRange(text.characters.count - 1, 1);
with this line:
let range = NSMakeRange((text as NSString).length - 1, 1);
That's it.
Works perfectly! Thank you!
Amazing work, no seriously ! =)