The following code will work fine in iOS < 7.0. In iOS 7 the scrolling will be choppy and erratic while the UITextView is updating. I\'m not sure if this is a bug in iO
Swift 2.0 - IOS 8
This is basically a Swift 2.0 version of dklt's answer above. Previously I was using the same method without the 2 lines of scrollEnabled
. Most of the time it works fine. However, when scrollToBottom()
is called in quick succession at almost the same time, it doesn't works sometimes.
The 2 lines of scrollEnabled
doesn't makes much sense, but after adding them the method works consistently!
Note: I have tried to put the 2 lines of scrollEnabled
in various position before or after the scrollRangeTovisible
, as was suggested in dklt's answer's comments...
ONLY dklt's original solution works for me. The rest doesn't.
func scrollToBottom()
{
let range:NSRange = NSMakeRange(self.textView.text.characters.count - 1, 1)
self.textView.scrollRangeToVisible(range)
self.textView.scrollEnabled = false
self.textView.scrollEnabled = true
}
Basically setScrollEnabled = YES need to be set before layoutSubviews get called. It worked for me.
For those who are using Swift, I post here the same answer as RawMean (thanks again!). As I wrote this (dec. 2014), the problem still exist in iOS 8.1 and his solution work perfectly...
var textView: UITextView!
var textStorage: NSTextStorage!
var layoutManager: NSLayoutManager!
var textContainer: NSTextContainer!
override func viewDidLoad() {
textStorage = NSTextStorage()
layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let newTextViewRect = view.bounds
let containerSize = CGSize(width: newTextViewRect.width, height: CGFloat.max)
textContainer = NSTextContainer(size: containerSize)
layoutManager.addTextContainer(textContainer)
textView = UITextView(frame: newTextViewRect, textContainer: textContainer)
textView.delegate = self
view.addSubview(textView)
}
override func viewDidLayoutSubviews() {
textView.frame = view.bounds
}
and I used the scrollRangeToVisible method to scroll smoothly at the bottom as text is added...
let length = countElements(textView.text)
let range:NSRange = NSMakeRange(length - 1, 1)
textView.scrollRangeToVisible(range)