Help us understand the problem. What is going on with this article?

UIButtonでtoolbar付きのKeyboardを出したい

More than 1 year has passed since last update.

これの続き
UIButtonを押すとキーボードが出てくるようにする

UItextFiledだったらinputAccessoryViewに入れたいツールバーを入れたらいいとのことだったが、UIButtonを拡張した場合ちょっと詰まったのでメモ

右下の赤色のボタンを押すと ツールバー付きのキーボードが出てくるようにしたい

解決策

このクラスを使ったボタンであれば押すとキーボードが出てくるようになっています

class RespondingButton: UIButton, UIKeyInput {

    override var canBecomeFirstResponder: Bool {
        return true
    }

    let toolbar :UIToolbar = {
        let toolbar = UIToolbar()
        let flexibleItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
        let okButton: UIBarButtonItem = UIBarButtonItem(title: "OK", style: UIBarButtonItem.Style.plain, target: self, action: #selector(TargetListViewController.openLeftMenu))
        let cancelButton: UIBarButtonItem = UIBarButtonItem(title: "CANCEL", style: UIBarButtonItem.Style.plain, target: self, action: #selector(TargetListViewController.openLeftMenu))
        // アイテムを配置
        toolbar.setItems([flexibleItem, okButton, flexibleItem, cancelButton, flexibleItem], animated: true)
        // ツールバーのサイズを指定
        toolbar.sizeToFit()

        return toolbar
    }()

    //private let accessoryView = UIView()
    override var inputAccessoryView: UIView {
        return self.toolbar
    }
    var hasText: Bool = true
    func insertText(_ text: String) {}
    func deleteBackward() {}
}

調査の経緯

【Swift4】キーボードの上にUIToolbarを実装する方法
こちらを参照してinputAccessoryViewtoolbarを入れたら良さそうということはわかるが、UIButtonを拡張している場合,拡張したUIButtonにinputAccessoryViewが存在しているのかどうなのかがさっぱりわからなかった

Appleのドキュメントを確認

Apple inputAccessoryView
こちらを参照する

受信者が最初のレスポンダになったときに表示されるカスタム入力アクセサリビュー

UIButtonクラスの親クラスはUIResponderを継承しているのでinputAccessoryViewを持っているはず・・・
なのに

button.inputAccessoryView = toolbar

でエラーを吐かれてしまう

説明をよく読んでみると

This property is typically used to attach an accessory view to the system-supplied keyboard 
that is presented for UITextField and UITextView objects.

The value of this read-only property is nil. 
If you want to attach custom controls to a system-supplied input view 
(such as the system keyboard) or to a custom input view (one you provide in the inputView property), redeclare this property as read-write in a UIResponder subclass. 
You can then use this property to manage a custom accessory view. 
When the receiver becomes the first responder, the responder infrastructure attaches the accessory view to the appropriate input view before displaying it.

つまりこのプロパティは read-only property です
カスタム入力ビューで使うならこのプロパティをUIResponderサブクラスの読み書き可能として再宣言してねとのことでした

再宣言・・? :thinking:

再宣言のやり方を調べる

こちらの文献を参考にしました
How do I redeclare a property as read-write in UIResponder subclass with swift?

こういうふうにすれば良さそうということがわかった

private let accessoryView = AccessoryView()
class MessagesViewController : UIViewController {
    override var inputAccessoryView: AccessoryView {
        return accessoryView
    }
}

とりあえず拡張したUIButtonクラス内に入れたいツールバーを作って、inputAccessoryViewに入れることでできた :clap:

参考文献

【Swift4】キーボードの上にUIToolbarを実装する方法
How do I redeclare a property as read-write in UIResponder subclass with swift?

nakagawa1017
iOSエンジニアしてます 好きなもの Adobe.Ai.AE.Ps/Sketch/Blender/デジタルファブリケーション
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away