コードを日本語へ! Swift UITextField, UITextViewがキーボードで隠れるのを防ぐ(UIScrollViewを使わずに)
参考にさせていただきました。
【Swift】UITextField, UITextViewがキーボードで隠れるのを防ぐ(UIScrollViewを使わずに) - Qiita
//UITextViewDelegateを実装 class HogeHogeController: UIViewController,UITextViewDelegate { //このテキストビューを動かします @IBOutlet weak var content: UITextView!{ didSet{ content.delegate = self } } @IBAction func btn_decide(_ sender: Any) { } override func viewDidLoad() { super.viewDidLoad() } //テキストビューの入力が始まったときに呼ばれるメソッド。 // 一番初めのクラス定義でUITextViewDelegateを実装しているので自然と呼ばれます。 func textViewShouldBeginEditing(_ textView: UITextView)-> Bool{ content.resignFirstResponder() return true } //監視開始 viewWillAppearで呼んでおくと、何度でも呼び出してくれます。 override func viewWillAppear(_ animated: Bool) { configureObserver() } //監視解除 画面が遷移または消えるときに呼ばれます。 override func viewWillDisappear(_ animated: Bool) { removeObserver() } //値監視の関数 下記に説明します。説明1 func configureObserver(){ // let notification = NotificationCenter.default //ここでどんな関数を呼び出すかを決めます。 notification.addObserver(self, selector: //keyboardWillShow(自分で作った関数)が呼ばれます。 #selector(keyboardWillShow(notification:)), //これはアップルの指定の属性 name: UIResponder.keyboardWillShowNotification, object: nil) //キーボードが隠されるときにも値を監視します。なんでも、呼んだら、隠す。これがセットになる。 //飲んだら、乗るな。飲むなら乗るな これがセットになっている。 //ちなみに若いときには、 吐くなら飲むな というのもある。 //年齢が行くと、吐いてまででも飲まないといけない。フリーランスのつらいところ notification.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) } //監視を外す関数も作っておく。関数名は自分で自由につけるが、中身はほとんど同じになる。 func removeObserver(){ let notification = NotificationCenter.default notification.removeObserver(self) } //セレクターで呼ばれた関数の前には @objc をつけてあげる。これが作法。 //詳しく書くとこのあたりのアップルの関数は、昔のObjective-Cで書かれているのである。 @objc func keyboardWillShow(notification: Notification){ //キーボードの動く量を取ってきている。それぞれの機種でキーボードサイズが異なるため。 let rect = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue //Viewが動く時間。これを決めておかないと、引数に指定されているので、従う。 let duration: TimeInterval? = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double //Viewを動かす。animateメソッド。 //ここに移動量を設定。クロージャーになっている。説明-2 UIView.animate(withDuration: duration!, animations: { () in let transform = CGAffineTransform(translationX: 0, y: -(rect?.size.height)!) self.view.transform = transform }) } // キーボードが消えたときに、画面を戻す @objc func keyboardWillHide(notification: Notification) { let duration: TimeInterval? = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? Double UIView.animate(withDuration: duration!, animations: { () in self.view.transform = CGAffineTransform.identity }) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { } @IBAction func backButton(_ sender: Any) { self.dismiss(animated: true, completion: nil) } }
説明-1 NotificationCenter とは Notificationとの違い
設定したものに対し、値が変更したときに、教えてくれるもの addObserverメソッドでいくらでも追加できる。 そのときに呼ばれるメソッドをセレクターで設定し、その関数を呼ぶ。
Notification は NotificationCenterを介して渡される通知の事
郵便局がNotificationCenter で 手紙が Notification こう考えるとわかりやすい
説明-2 移動量がクロージャーになっているわけ。
//ここに移動量を設定。クロージャーになっている。説明-2 //{からがクロージャー UIView.animate(withDuration: duration!, animations: { () in let transform = CGAffineTransform(translationX: 0, y: -(rect?.size.height)!) self.view.transform = transform
まだ、キーボードが出ていないのに動いてはいけない。
クロージャーの中身は、飛ばされて、中身に値が整った時点で、呼び出される。
クロージャーの中で、移動量が設定されている。
よって移動量が決まるまでは呼ばれない。
キーボード入力に成るまで呼ばれないということ。