【Swift】キーボードにUIDatePickerを表示する

# １．はじめに

　以前、[【Swift】キーボードにUIPickerViewを表示する](https://qiita.com/wai21/items/765206fdc37b2c258481)という記事を投稿しました。
　これをちょっとだけ応用して`UITextField` と`UIDatePicker` を使った日付選択のUIを作りました。
　やる事は上記の記事と同様です。`UITextField` の`inputView` に `UIDatePicker` を設定し、`inputAccessoryView` に完了ボタンや今日の日付に設定するボタンを配置したツールバーを設定します。


# ２．環境
Xcode Version 9.4.1
Swift Version 4.1.2

# ３．完成形
<img width="375" alt="Simulator Screen Shot - iPhone X - 2018-09-16 at 17.31.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/124577/bf5affcb-2629-2df3-38f9-9b8a4e4c7b48.png">

# ４．コード全体

```swift
class DatePickerKeyboard: UITextField {
    private var datePicker: UIDatePicker!
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commoninit()
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        commoninit()
    }
    private func commoninit() {
        // datePickerの設定
        datePicker = UIDatePicker()
        datePicker.date = Date()
        datePicker.datePickerMode = .date
        datePicker.locale = Locale(identifier: "ja")
        datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)
        
        // textFieldのtextに日付を表示する
        setText()
        
        inputView = datePicker
        inputAccessoryView = createToolbar()
    }
    
    // キーボードのアクセサリービューを作成する
    private func createToolbar() -> UIToolbar {
        let toolbar = UIToolbar()
        toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: 44)

        let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
        space.width = 12
        let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let todayButtonItem = UIBarButtonItem(title: "今日", style: .done, target: self, action: #selector(todayPicker))
        let doneButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePicker))

        let toolbarItems = [flexSpaceItem, todayButtonItem, doneButtonItem, space]

        toolbar.setItems(toolbarItems, animated: true)

        return toolbar
    }
    
    // キーボードの完了ボタンタップ時に呼ばれる
    @objc private func donePicker() {
        resignFirstResponder()
    }
    // キーボードの今日ボタンタップ時に呼ばれる
    @objc private func todayPicker() {
        datePicker.date = Date()
        setText()
    }
    
    // datePickerの日付けをtextFieldのtextに反映させる
    @objc private func setText() {
        let f = DateFormatter()
        f.dateStyle = .long
        f.locale = Locale(identifier: "ja")
        text = f.string(from: datePicker.date)
    }
    
    // クラス外から日付を取り出すためのメソッド
    func getDate() -> Date {
        return datePicker.date
    }
    
    // コピペ等禁止
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
    // 選択禁止
    override func selectionRects(for range: UITextRange) -> [Any] {
        return []
    }
    // カーソル非表示
    override func caretRect(for position: UITextPosition) -> CGRect {
        return CGRect(x: 0, y: 0, width: 0, height: 0)
    }
}

```

# ５．ポイント

・`UITextField` のサブクラスを作成します。
・`UIDatePicker` 以外で`UITextField` の値を変更させたくないので、通常のキーボード入力時に表示されるカーソルやコピペ用のUIを`canPerformAction` 、`selectionRects` 、`caretRect` で無効にしています。
・`UIDatePicker` で日付を変更するたびに`UITextField` の値を変更させるために`datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)` を初期化時に行います。
・`UIDatePicker` の設定やカスタマイズはお好みで。
・ツールバーの「今日」ボタンを押下した時に`datePicker.date` に`Date()` を設定し、ピッカーの値を現在日時に変更します。