はじめに
UIButtonを押すとキーボードが出てくるようにしたい
参考文献によるとUIButtonを継承、UIKeyInputプロトコルを適合させたものを使うといいとのことだった
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
このオブジェクトが最初のレスポンダになることができるかどうかを示すブール値を返します。
このメソッドはデフォルトでfalseを返します。サブクラスはこのメソッドをオーバーライドし、trueを返してファーストレスポンダになることができるようにする必要があります。
現在アクティブなビュー階層にないビューでは、このメソッドを呼び出さないでください。結果は未定義です。
そもそもこのプロパティはどこにいるかというと、
UIButton←UIControl←UIView←UIResponderをめぐりUIResponder
内にいることがわかる
UIResponder
とはイベントに応答し処理するための抽象インタフェースのこと
つまり、UIButtonではこのcanBecomeFirstResponder
プロパティはデフォルトでfalseになっているので、オーバーライドしてプロパティを書き直す必要があるとのことだ
UIKeyInput
プロトコルを調べる
UIKeyInput
はUITextInputTraits
を継承しているプロパティ
こいつを適合させると下記3つのプロパティとメソッドを書く必要がある
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
になっているのではないかと思う(ソースは調査中)
3つのメソッドとプロパティを調べる
Appleのドキュメントの下のプロパティメソッド一覧にRequired.
とついていて親切だなと思った
func insertText(String)
表示されているテキストに文字を挿入します。 必須。
カーソルに対応するインデックスにあるクラスのバッキングストアに文字テキストを追加して、テキストを再表示します。
deleteBackward()
表示されているテキストから文字を削除します。
クラスのバッキングストアからカーソルの直前の文字を削除して、テキストを再表示します。
hasText
テキスト入力オブジェクトにテキストがあるかどうかを示すブール値。
バッキングストアにテキストコンテンツがある場合はtrue、そうでない場合はfalse
Apple hasText
この押すとキーボードが出てくるボタンをつくるのに
テキスト入力オブジェクトにテキストがあるかどうかを示すブール値はtrue
表示されているテキストから文字を削除する → とくに設定しない
表示されているテキストに文字を挿入する → 特に設定しない
というようにしているとのことだった
(使い方はいまいち把握できてないので今度調査する)
UITextInputTraits
を調べる
UIKeyInput
の親プロトコル?のUITextInputTraits
も気になったので調べた
テキストオブジェクトへのキーボード入力に関連する機能を定義するメソッドのコレクション
カスタムテキストオブジェクトがキーボード入力をサポートするには、テキスト入力管理システムと正しく対話するためにこのプロトコルを採用する必要があります。 UITextFieldクラスとUITextViewクラスは自動的にこのプロトコルをサポートします。
プロパティを見た感じキーボードの外観や、入力に関する細かい設定ができる
たとえば今回の参考文献で紹介されていたボタンを押して
数字を押す形式のキーボードを出したい場合は下記のように設定を変更できる
プロトコルが定義されているところを見て
optional
→適合先でこのプロパティを書いても書かなくてもどっちでも良い
public
→ クラス外からでも参照できる
var
→ 変数
keyboardType
→ keyboardType
という名前のプロパティ
UIKeyboardType
→ UIKeyboardType
という型のものをがはいっている
{ get set }
→ このプロパティから値を取れるし入れることができる
public protocol UITextInputTraits : NSObjectProtocol {
~~~~ 省略 ~~~~
optional public var keyboardType: UIKeyboardType { get set } // default is UIKeyboardTypeDefault
~~~~ 省略 ~~~
UIKeyboardType
は下記のように定義されているので、このなかのどれかのcaseを入れてあげればいい
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.
プロトコルで定義されているプロパティに適合先で値を入れればいいので下記のように書き直す
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