配置されたTextViewのテキストの量に応じてTableViewのCellの高さとTextViewの幅を動的に変更させる

##初めに
xibで作ったTableViewCellを想定しています

xibでのセルの作り方はこちらを参照ください
https://qiita.com/Secret-Base36/items/2a9a3989479559ba36ba

##環境
Xcode 12.2

##1. TextViewの設定

 - Scrolling Enableのチェックを外す

![スクリーンショット 2020-12-07 20.35.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/32edb641-59d4-4f4a-d56e-255c81ebb75e.png)


##2. TableViewのセルの高さの設定

TableViewのheightForRowAtメソッドで可変に設定

```swift
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    //セルの推定最低高さ（不要？）
    secondTableView.estimatedRowHeight = 50
    //セルの高さを可変に設定
    return UITableView.automaticDimension
  }
```
estimatedRowHeight（セルの推定高さ）は記述しなくても結果は変わらなかった

##ここまでの結果
![スクリーンショット 2020-12-07 21.28.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/67566b74-d621-2e25-0193-ca8b24d97701.png)

文字量によってセルの高さが変わる様になった！

###微調整

上の図の様に最小高さの場合に、他のUIが重なるなど影響が出る場合は、制約で調整すると良い

![スクリーンショット 2020-12-07 21.31.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/877b9235-6f42-44eb-35e8-1456d769a45b.png)

![スクリーンショット 2020-12-07 21.39.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/83a3d467-88b2-ee7f-b9c7-a0b2ea0912e3.png)


####ここまでで高さを動的に変更させるまでは終わり

ここからは、幅も動的に変更させる方法

##3.textからViewの幅を計算する
TableViewCellのクラスにメソッドを追加する

```SecondTableViewCell.swift
//セルのTextViewの幅の計算
  private func estimateFrameForTextView(text: String) -> CGRect{
    //最大値
    let size = CGSize(width: 200, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    
    return NSString(string: text).boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)], context: nil)
    //systemFont(ofSize）にはTextViewに設定したサイズを設定する
  }
```
##4.Textを受ける変数を定義して、幅の制約をCellのクラスとOutlet接続

![スクリーンショット 2020-12-13 15.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/123bf4af-41bf-d029-7c02-761f5cabeb9b.png)
接続名は"textViewWidthConstraint"としました


##5.作成したCell側の変数にTextを渡す

TableViewのcellForRowAtからCellのmsgText変数にテキストを格納

```SecondViewController.swift
  //セルの内容
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = secondTableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! SecondTableViewCell
    cell.backgroundColor = .lightText
    //cell.textView.text = textArray[indexPath.row]
    
    //★★★　Cellクラスの変数に格納　（ここで渡している）
    cell.msgText = textArray[indexPath.row]
    
    return cell
```

##6.Cellクラス側で幅を計算させて、TextViewの幅を変更するコードを書く

受け取ったテキストをもとに、estimateFrameForTextViewメソッドで幅を計算させて、その幅でTextViewの幅を変更する

```SecondTableViewCell.swift
//ViewControllerからテキストを受け取る変数
  var msgText :String? {
    //didSetで値の変更後（計算後）に通知
    didSet {
      //nilチェック
      guard let text = msgText else { return }
      //幅計算メソッドで幅を計算する　+ 10は幅に余裕を持たせる為（無いと不用意な改行が入ることも）
      let width = estimateFrameForTextView(text: text).width + 10
      
      textViewWidthConstraint.constant = width
      textView.text = text
    }
  }
```



####以上です

![スクリーンショット 2020-12-13 16.32.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/83f8200e-d47f-aff0-cc78-055f98582643.png)


##最後に
情報が間違っているなどありましたら、お手数ですがご指摘いただけると幸いです。
下に全コードを載せておきます

```SecondTableViewCell.swift
import UIKit

class SecondTableViewCell :UITableViewCell{
  
  //ViewControllerからテキストを受け取る変数
  var msgText :String? {
    //didSetで値の変更後（計算後）に通知
    didSet {
      //nilチェック
      guard let text = msgText else { return }
      //幅計算メソッドで幅を計算する　+ 10は幅に余裕を持たせる為（無いと不用意な改行が入ることも）
      let width = estimateFrameForTextView(text: text).width + 10
      
      textViewWidthConstraint.constant = width
      textView.text = text
    }
  }
  
  
  //★★★UIとの接続
  @IBOutlet weak var cellImageView: UIImageView!
  @IBOutlet weak var textView: UITextView!


  @IBOutlet weak var textViewWidthConstraint: NSLayoutConstraint!
  
  
  override func awakeFromNib() {
    super.awakeFromNib()
    
    //CellのUIのプロパティー変更
    cellImageView.layer.cornerRadius = 25
    
  }
  
  override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    
  }
  
  //セルのTextViewの幅の計算
  private func estimateFrameForTextView(text: String) -> CGRect{
    //最大値
    let size = CGSize(width: 200, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    
    
    return NSString(string: text).boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20)], context: nil)
    //systemFont(ofSize）にはTextViewに設定したサイズを設定する
  }
}

```

```SecondViewController.swift
import UIKit

class SecondViewController : UIViewController{
  
  
  private let cellId = "cellId"
  
  
  var textArray = ["あいうえお",
                   "あいうえお\nかきくけこ",
                   "あいうえおかきくけこさしすせそ",
                   "あいう\nえおかきくけこさしすせそ\nたちつてと"]
  
  
  @IBOutlet weak var secondTableView: UITableView!
  override func viewDidLoad() {
    super.viewDidLoad()
    
  
    
    
    secondTableView.delegate = self
    secondTableView.dataSource = self
    
    //セルの登録（Xibファイル名:SecondViewTableViewCell.xibの場合)
    secondTableView.register(UINib(nibName: "SecondViewTableViewCell", bundle: nil), forCellReuseIdentifier: cellId)
    

    
  }
}

extension SecondViewController :UITableViewDelegate,UITableViewDataSource{
  
  //セルの高さ
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    //Cellの高さを可変にする
    return UITableView.automaticDimension
  }
  //セルの個数
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return textArray.count
  }
  //セルの内容
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = secondTableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! SecondTableViewCell
    cell.backgroundColor = .lightText
    //cell.textView.text = textArray[indexPath.row]
    
    //Cellクラスの変数に格納
    cell.msgText = textArray[indexPath.row]
    
    return cell
  }
}
```