テキストの長さによって背景を動的に可変(見せかけを)するUITextView

# はじめに
こんにちは。
チャットアプリやメモアプリなどで利用するような
背景の長さが可変のUITextViewの実装に少し悩んだので書いてみました。
至らぬ点など多々あると思いますが、コメントなど頂けたら幸いです。

# サンプル
![sample.gif](https://qiita-image-store.s3.amazonaws.com/0/128250/ba107a87-9e6e-dcd6-40bb-3635484f0ded.gif)

# Storyboardの準備
実はUITextViewの高さが伸び縮みしているわけではなく
後ろに配置した背景色の付いたUIViewが動的に可変するようにしています。

**UIView(背景)の制約**

![UIViewConstraint.png](https://qiita-image-store.s3.amazonaws.com/0/128250/d458cd42-cb8c-08db-7b70-85cb1610d1ef.png)

**UITextViewの制約**

![UITextViewConstraint.png](https://qiita-image-store.s3.amazonaws.com/0/128250/707a6902-b099-ff97-4361-3025b6a58fbe.png)

また、**背景のUIViewのHeightのConstraint**と**UITextViewのbottomのConstraint**を
以下のようにIBOutlet接続します。
(画像ではUITextViewのbottomConstraintを繋げています。同じようにUIViewのHeightConstraintも接続してください。)

<img width="1191" alt="screen3.png" src="https://qiita-image-store.s3.amazonaws.com/0/128250/28aab14e-30ec-5c50-f0b5-c3a63e243bdc.png">

# 中身に合わせて背景UIViewが伸びすぎないように調節
UITextViewのHeightは以下のようになっています。

![UITextView_Height.png](https://qiita-image-store.s3.amazonaws.com/0/128250/a50b79f7-4e45-e139-d0a8-cde641e4ae27.png)

なので、伸びすぎた際はWindowのサイズ(見た目のサイズ)に合わせるように調節します。

```swift
if textView.frame.height <= textViewBackgroundView.frame.height {
    textViewBackgroundHeightConstraint.constant = textView.frame.size.height
}
```


# サンプルコード
```MainViewController.swift
import UIKit

class MainViewController: UIViewController {
    
    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var textViewBackgroundView: UIView!
    
    @IBOutlet weak var textViewBottomConstraint: NSLayoutConstraint!
    @IBOutlet weak var textViewBackgroundHeightConstraint: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
        NotificationCenter.default.addObserver(self,
        selector: #selector(MainViewController.showKeyBoard(_:)),
        name: NSNotification.Name.UIKeyboardWillShow,
        object: nil)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        textView.becomeFirstResponder()
        textView.tintColor = UIColor.black
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    //キーボードが表示された時の処理
    func showKeyBoard(_ notification: Notification) {
        if let userInfo = (notification as NSNotification).userInfo {
            if let keyboard = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue{
                textViewBottomConstraint.constant = keyboard.cgRectValue.size.height
            }
        }
    }
}

extension MainViewController: UITextViewDelegate {
    //textに変更があった際に呼び出される
    func textViewDidChange(_ textView:UITextView) {
        if textView.frame.height <= textViewBackgroundView.frame.height {
            textViewBackgroundHeightConstraint.constant = textView.frame.size.height
        }else {
            textViewBackgroundHeightConstraint.constant = textView.sizeThatFits(textView.frame.size).height
        }
    }
}
```

# 参考にさせていただいた記事
- [Apple リファレンス UITextView](https://developer.apple.com/reference/uikit/uitextview)

- [UIScrollViewが持つ2つのサイズについて u16suzuさんのブログより](http://u16suzu.hatenablog.com/entry/2013/07/10/182548)

見て頂いてありがとうございます。