UIButtonを押すとキーボードが出てくるようにする

# はじめに
UIButtonを押すとキーボードが出てくるようにしたい

参考文献によるとUIButtonを継承、UIKeyInputプロトコルを適合させたものを使うといいとのことだった

```Swift
class RespondingButton: UIButton, UIKeyInput {

    override var canBecomeFirstResponder: Bool {
        return true
    }

    var hasText: Bool = true
    func insertText(_ text: String) {}
    func deleteBackward() {}
}
```
# Appleの文献を読む
## `canBecomeFirstResponder`とはなにか
まずoverrideさせている`canBecomeFirstResponder`について調べてみる
[Apple canBecomeFirstResponder](https://developer.apple.com/documentation/uikit/uiresponder/1621130-canbecomefirstresponder)

> このオブジェクトが最初のレスポンダになることができるかどうかを示すブール値を返します。

> このメソッドはデフォルトでfalseを返します。サブクラスはこのメソッドをオーバーライドし、trueを返してファーストレスポンダになることができるようにする必要があります。 
> 現在アクティブなビュー階層にないビューでは、このメソッドを呼び出さないでください。結果は未定義です。

そもそもこのプロパティはどこにいるかというと、
UIButton←UIControl←UIView←UIResponderをめぐり`UIResponder`内にいることがわかる
`UIResponder`とはイベントに応答し処理するための抽象インタフェースのこと

つまり、UIButtonではこの`canBecomeFirstResponder`プロパティはデフォルトでfalseになっているので、オーバーライドしてプロパティを書き直す必要があるとのことだ

## `UIKeyInput`プロトコルを調べる
`UIKeyInput`は`UITextInputTraits`を継承しているプロパティ
こいつを適合させると下記３つのプロパティとメソッドを書く必要がある

```Swift
public protocol UIKeyInput : UITextInputTraits {

    
    public var hasText: Bool { get }

    
    public func insertText(_ text: String)

    public func deleteBackward()
}
```
Appleのドキュメントによると
> UIResponderのサブクラスが単純なテキスト入力を実装するために使用する一連のメソッド。

とのこと

> このサブクラスのインスタンスが最初のレスポンダの場合、システムキーボードが表示されます。
> このプロトコルを採用しているクラスでは、利用可能なキーボードと言語のごく一部しか利用できません。

`UITextField`の定義を見てみると下記のようにこのプロトコルが適合されている

```
@available(iOS 2.0, *)
open class UITextField : UIControl, UITextInput, NSCoding, UIContentSizeCategoryAdjusting {

```

だから自動でキーボードが出てくるようになっているのだと思う
おそらく`canBecomeFirstResponder`も`true`になっているのではないかと思う(ソースは調査中)

### ３つのメソッドとプロパティを調べる
Appleのドキュメントの下のプロパティメソッド一覧に`Required.`とついていて親切だなと思った

#### `func insertText(String)`

> 表示されているテキストに文字を挿入します。 必須。
> カーソルに対応するインデックスにあるクラスのバッキングストアに文字テキストを追加して、テキストを再表示します。

[Apple insertText(_:)](https://developer.apple.com/documentation/uikit/uikeyinput/1614543-inserttext)

#### `deleteBackward()`
> 表示されているテキストから文字を削除します。
> クラスのバッキングストアからカーソルの直前の文字を削除して、テキストを再表示します。

#### `hasText`
> テキスト入力オブジェクトにテキストがあるかどうかを示すブール値。
> バッキングストアにテキストコンテンツがある場合はtrue、そうでない場合はfalse
[Apple hasText](https://developer.apple.com/documentation/uikit/uikeyinput/1614457-hastext)


この押すとキーボードが出てくるボタンをつくるのに
テキスト入力オブジェクトにテキストがあるかどうかを示すブール値はtrue
表示されているテキストから文字を削除する　→　とくに設定しない
表示されているテキストに文字を挿入する　→　特に設定しない

というようにしているとのことだった
（使い方はいまいち把握できてないので今度調査する）

## `UITextInputTraits`を調べる
`UIKeyInput`の親プロトコル？の`UITextInputTraits`も気になったので調べた

> テキストオブジェクトへのキーボード入力に関連する機能を定義するメソッドのコレクション
> カスタムテキストオブジェクトがキーボード入力をサポートするには、テキスト入力管理システムと正しく対話するためにこのプロトコルを採用する必要があります。 UITextFieldクラスとUITextViewクラスは自動的にこのプロトコルをサポートします。

プロパティを見た感じキーボードの外観や、入力に関する細かい設定ができる

[UITextInputTraits](https://developer.apple.com/documentation/uikit/uitextinputtraits)

たとえば今回の参考文献で紹介されていたボタンを押して
数字を押す形式のキーボードを出したい場合は下記のように設定を変更できる

プロトコルが定義されているところを見て

`optional `→適合先でこのプロパティを書いても書かなくてもどっちでも良い
`public`　→　クラス外からでも参照できる
`var`　→　変数
`keyboardType`　→　`keyboardType`という名前のプロパティ
`UIKeyboardType` →　`UIKeyboardType`という型のものをがはいっている
` { get set }`  →　このプロパティから値を取れるし入れることができる

```Swift
public protocol UITextInputTraits : NSObjectProtocol {

~~~~ 省略 ~~~~
optional public var keyboardType: UIKeyboardType { get set } // default is UIKeyboardTypeDefault
~~~~ 省略　~~~

```

`UIKeyboardType`は下記のように定義されているので、このなかのどれかのcaseを入れてあげればいい

```Swift
public enum UIKeyboardType : Int {

    
    case `default` // Default type for the current input method.

    case asciiCapable // Displays a keyboard which can enter ASCII characters

    case numbersAndPunctuation // Numbers and assorted punctuation.

    case URL // A type optimized for URL entry (shows . / .com prominently).

    case numberPad // A number pad with locale-appropriate digits (0-9, ۰-۹, ०-९, etc.). Suitable for PIN entry.

    case phonePad // A phone pad (1-9, *, 0, #, with letters under the numbers).

    case namePhonePad // A type optimized for entering a person's name or phone number.
```

プロトコルで定義されているプロパティに適合先で値を入れればいいので下記のように書き直す

```Swift
class RespondingButton: UIButton, UIKeyInput {

    override var canBecomeFirstResponder: Bool {
        return true
    }

    var hasText: Bool = true
    func insertText(_ text: String) {}
    func deleteBackward() {}
    var keyboardType: UIKeyboardType = .numberPad

}

```

#参考文献
[iOS - UIButton become first responder to open keyboard](https://stackoverflow.com/questions/45491518/ios-uibutton-become-first-responder-to-open-keyboard)