メッセージ送信用InputAccesorryViewの作成

###完成形

inputAccesorryViewにxibで作ったテキストの入力欄と送信ボタンを配置、
テキストを入力してボタンを押すとViewControllerにある表示用のTextViewにテキストを表示する。

ViewControllerへのテキストの受け渡しはDelegateで行う。

![スクリーンショット 2020-12-13 10.14.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/d1bf2776-dbc3-2230-a275-6a35ca098978.png)

##はじめに

StoryboardでNavigationControllerと入力したテキストを表示するTextViewを適当に配置
TextViewはViewController.swiftに"displayTextView"と言う名前でOutlet接続しておきます

![スクリーンショット 2020-12-08 20.46.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/2372c3e8-b3fb-fc28-e3e0-53ad6ffb5687.png)


##1.xibファイルの作成


####プロジェクトフォルダの任意の位置で、New File...を選択
![スクリーンショット 2020-12-08 20.52.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/f4119873-6f53-af11-71f0-c566eb99286f.png)

####Viewを選択してファイル名を入力してCreate
![スクリーンショット 2020-12-08 20.56.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/9b2b20a9-fa0c-5da9-98b7-cee5632657d7.png)

##2.UIの作成

SizeをFreeFormに変更してフォームの形を適当にそれっぽくする。
![スクリーンショット 2020-12-08 21.10.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/c169a2dc-d504-0a36-a700-3aeeb62527a6.png)


####メッセージを入力するTextViewとButtonを配置
TextViewの上下と左の制約を10にしてAdd Constraints
(下の制約はSafeAreaから指定するのがポイント）

![スクリーンショット 2020-12-08 21.20.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/ce8e2106-6397-ac50-2011-456676f489e2.png)


####ボタンのVertically in Containerをチェックして制約を追加
![スクリーンショット 2020-12-08 21.27.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/f48fa54a-aec0-ca11-20fb-13b2be128a1c.png)

####TextViewとButtonの縦センターを合わせる

上のButtonのVertically in Containerで設定した縦センターの制約の設定を下図の様に変更して
TextViewのセンターとButtonのセンターを合わせる
![スクリーンショット 2020-12-08 21.37.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/15dc953a-d28f-8913-6081-c5c34b79ac76.png)

####ボタンの左右と幅の制約をかける
![スクリーンショット 2020-12-08 22.29.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/7d62da8b-2a32-608e-c654-ac65fd79dc3e.png)


####TextViewのScrolling Enableのチェックを外す
![スクリーンショット 2020-12-09 22.26.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/8a009c19-a515-618a-2300-18815bbb8730.png)

以上でUIの作成は終わり

##3.xib用のUIViewのクラスを作成

####swiftファイルを作成して、以下のコードを入力

ひとまずxibに設定できるように仮でUIViewクラスを作成しておく

```MsgInputAccessoryView.swift
import UIKit

class MsgInputAccessoryView: UIView {
  
  override init(frame: CGRect) {
    super.init(frame: frame)
  }
 
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}
```

####xibのFile's OwnerにUIViewのClassを設定

![スクリーンショット 2020-12-09 21.58.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918084/a2935290-c89a-8fd3-abf8-c07d6019d4e3.png)

####作成しておいたUIView ClassにUIを接続してコーディング

```MsgInputAccessoryView.swift
import UIKit

//入力したtextをViewControllerに伝えるDelegate (:classは循環参照防止）
protocol MsgInputAccessoryViewDelegate :class {
  func tapedSendButton(text: String)
  
}

class MsgInputAccessoryView: UIView {
  
  @IBOutlet weak var msgTextView: UITextView!
  @IBOutlet weak var sendButton: UIButton!
  
  //sendButtonが押されたときに呼ばれる
  @IBAction func tapedSendButton(_ sender: Any) {

    guard let text = msgTextView.text else { return }
    //delegateに入力した値を渡す
    delegate?.tapedSendButton(text: text)
    
  }
  
  weak var delegate : MsgInputAccessoryViewDelegate?
  
  
  override init(frame: CGRect) {
    super.init(frame: frame)
    
    //viewの貼り付け
    nibInit()
    setupViews()
    //msgTextViewの高さを可変にする設定①
    autoresizingMask = .flexibleHeight
  }
  
  
  private func setupViews(){
    
    msgTextView.layer.cornerRadius = 15
    //未入力では押せない様にしておく
    sendButton.isEnabled = false
    
    //初期は空欄にしておく
    msgTextView.text = ""
    msgTextView.delegate = self

  }
  
  //send後の処理(ViewControllerから実行）
  func removeText(){
    
    msgTextView.text = ""
    sendButton.isEnabled = false
  }
  
  //msgTextViewの高さを可変にする設定②
  override var intrinsicContentSize: CGSize{
    return .zero
  }
  
  //xibのロードメソッド
  private func nibInit(){
    
    let nib = UINib(nibName: "MsgInputAccessoryView", bundle: nil)
    //xibのFile's Ownerにclassを紐付ける
    guard let view = nib.instantiate(withOwner: self, options: nil).first as? UIView else { return }
    
    view.frame = self.bounds
    //親のViewサイズが変わった時に、子のViewサイズや位置を自動的に調整できる様に設定
    view.autoresizingMask = [.flexibleHeight,.flexibleWidth]
    
    //ただのUIViewなので、UINib.instantiate(self).firstから取得しProfileViewに対してaddSubviewする
    self.addSubview(view)
  }
  
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

extension MsgInputAccessoryView: UITextViewDelegate{
  //textViewが編集されるたびに呼ばれる
  func textViewDidChange(_ textView: UITextView) {
    if textView.text.isEmpty {
      //inputTextViewが空欄だったらsendButtonを無効化にする
      sendButton.isEnabled = false

    }else{
      sendButton.isEnabled = true
      
    }
  }
}
```

##4.受け取ったテキストを表示するViewControllerのコーディング

InputAccessoryViewにセットして、Delegateでテキストを受け取ったテキストをTextViewに表示する

```ViewController.swift
import UIKit

class ViewController: UIViewController {

  @IBOutlet weak var displayTextView: UITextView!
  //viewにframeサイズを与えてインスタンス化(クロージャー式　定義と同時にプロパティーに値を与える）
  //lazyをつけてdelegateでselfにアクセスできる様にする
  private lazy var msgInputAccessoryView: MsgInputAccessoryView = {
    
    let view  = MsgInputAccessoryView()
    view.frame = .init(x: 0, y: 0, width: view.frame.width, height: 100)
    view.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 100)
    //MsgInputAccessoryViewで設定したdelegate
    view.delegate = self
    return view
    
  }()
  
  
  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  }
  
  
  //viewControllerに元々あるinputAccessoryViewにUIViewをセット
  override var inputAccessoryView: UIView?{

   // get{
      return msgInputAccessoryView
    //}
  }

  //初めからmsgInputAccessoryViewが表示される様に
  //ViewController(self)のcanBecomeFirstResponderをtrueに書き換え
  override var canBecomeFirstResponder: Bool{
    return true

  }
}

//MsgInputAccessoryViewからdelegateで値を受け取る
extension ViewController: MsgInputAccessoryViewDelegate{
  func tapedSendButton(text: String) {
    print(text)
    
    displayTextView.text = text
    
    //値を受け取った時点で、msgTextViewのクリアを実行
    msgInputAccessoryView.removeText()
    
  }
}
```

以上で終わりです

##最後に
間違いなどありましたらご指摘いただけると幸いです