Swift で動的に高さを変更するチャット入力欄を実装する:改

チャットの入力欄のように、文字列の長さによって入力欄の高さが動的に変わる UITextView の実装となりますが、一般的には、 https://hacknote.jp/archives/7958/ のように textViewDidChangesizeThatFits を呼び出して高さを設定する方法が多いと思います。

ただし、この方法の場合、カーソルや描画がちらついてしまうことがあります。 なお、GlowingTextView でも同様の現象が起こりまして、このライブラリを利用している slack などでも発生するようです。
https://github.com/HansPinckaers/GrowingTextView
サイズを計算する sizeThatFits というメソッドですが、計算時にどうやら描画にも影響を与えているようです。

この現象を改善した、手法として、以下のようにダミーの UITextViewsizeThatFits でサイズを計算し、 文字入力が画面に反映される前に、高さを変更してしまう方法があります。

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {

    var dummyText: NSMutableString = NSMutableString(string: textView.text)
    dummyText.deleteCharactersInRange(range)
    dummyText.insertString(text, atIndex: range.location)

    let maxHeight:CGFloat = 100.0
    let minHeight:CGFloat = 33.0

    dummyTextView.frame = CGRectMake(0, 0, textView.frame.width, textView.frame.height)
    dummyTextView.font = textView.font
    dummyTextView.text = dummyText as String

    var size = dummyTextView.sizeThatFits(textView.frame.size)

    var height = size.height
    if(height < minHeight) {
        height = minHeight
    }
    if(height > maxHeight) {
        height = maxHeight
    }
    if (textFieldHeight.constant != height) {
        var offsetY = (textFieldHeight.constant - height)
        if((offsetY > 0 && height > maxHeight - offsetY) || (offsetY < 0 && height > maxHeight)) {
            offsetY = 0
        }
        tableView.contentOffset.y = tableView.contentOffset.y - offsetY

        textFieldHeight.constant = height
    }

     return true
}