とこなつとこなつ

swift について勉強したことの忘備録とか

UITextField (UITextView) を IBOutlet 接続せずにキーボードで隠れないようにする。

テキストフィールドやテキストビューがキーボードに隠れてしまうので、それにあわせて scrollView を移動させるやり方を勉強したのでメモ。
サンプルとかはググったら色々出てくるんだけど、テキストフィールドを IBOutlet で接続してやる方法が多かった。
それだと、view にテキストフィールドがたくさん乗ってるときは使いにくいなと思いました。

@IBOutlet weak var textField1: UITextField!

…

@IBOutlet weak var textField5: UITextField! 

できれば↑はしたくないということで、作ってみたコードをぺたり。

class ViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {

    @IBOutlet weak var scrollView: UIScrollView!
    var frameOrigin:CGRect = CGRect(x: 0, y: 0, width: 0.0, height: 0.0)

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func viewWillAppear(animated: Bool) {
        // notification 登録
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
    }

    // 画面がタップされたときに呼ばれる
    @IBAction func tapped(sender: AnyObject) {
        // キーボードを非表示にする
        self.view.endEditing(true)
    }

    func textFieldShouldReturn(textField: UITextField) -> Bool {
        // フォーカスを外す(キーボードを非表示にする)
        textField.resignFirstResponder()
        return true
    }

    func textFieldDidBeginEditing(textField: UITextField) {
        // キーボードの出たときの移動の判定用にとっておく
        self.frameOrigin = CGRect(x: textField.frame.origin.x, y: textField.frame.origin.y, width: textField.frame.size.width, height:textField.frame.size.height)
    }

    // keyboardWillShow より先に呼ばれる(did ではダメ)
    func textViewShouldBeginEditing(textView: UITextView) -> Bool {
        // キーボードが出た際に scrollview の移動判定用にとっておく
        self.frameOrigin = CGRect(x: textView.frame.origin.x, y: textView.frame.origin.y, width: textView.frame.size.width,  height: textView.frame.size.height)
        return true
    }

    func keyboardWillShow(notification: NSNotification?) {
        // キーボードの情報を取得
        let rect = (notification?.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
        // view の底からの高さ
        let textHeight = self.view.frame.height - self.frameOrigin.origin.y - self.frameOrigin.size.height
        let keyboardHeignt = rect.size.height

        // キーボードで隠れてしまうか
        if (keyboardHeignt > textHeight)
        {
            // キーボードで隠れるので、scrollView を移動させる
            let margin = CGFloat(5.0)
            let point = CGPoint(x: 0, y: keyboardHeignt - textHeight + margin)
            // テキストフィールド(ビュー)がキーボードの上に来るように移動
            self.scrollView.setContentOffset(point, animated: false)
        }
    }
    func keyboardWillHide(notification: NSNotification?) {
        // キーボードが非表示になるので、scrollView を元に戻す
        self.scrollView.setContentOffset(CGPoint(x: 0.0, y: 0.0), animated: false)
    }
}

UITextField と UITextView は StoryBoard 上で ViewController の Delegate と接続しています。
しかし、読みにくすぎますね。
f:id:tokonatsutan:20150705201111p:plainf:id:tokonatsutan:20150705201122p:plain
キーボードにテキストビューが隠れてませんね。とりあえずできた。
もっといい方法があれば教えていただければ幸いです。