Как связать кнопки XIB на пользовательской встроенной клавиатуре (Swift 4)

#ios #swift

#iOS #swift

Вопрос:

Я только что создал пользовательскую клавиатуру в приложении, прошел через все сложные вещи, но теперь я в тупике (что, вероятно, тривиально):

как соединить кнопки XIB и связанного с ним класса, чтобы соответствующий текст вводился в UITextView на ViewController.

Я создал XIB с клавиатурой, чтобы я мог повторно использовать одну и ту же клавиатуру в разных контроллерах. Установите все ограничения, классы, владельца файла и т. Д. Все работает отлично, за исключением получения данных из ключа в представление.

Вот что у меня есть:

 class ViewController: UIViewController, UITextViewDelegate {

    @IBOutlet weak var inputField: UITextView!
    @IBOutlet weak var customKeyboard: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        inputField.delegate = self        
    }
}

class CustomKeyboard: UIView {

    @IBOutlet var contentView: UIView!
    
    @IBOutlet weak var key1: UIButton!
    @IBOutlet weak var key2: UIButton!
    // etc.
    @IBOutlet weak var keyReturn: UIButton!
    @IBOutlet weak var keyDelete: UIButton!
    
    
    override init(frame: CGRect) {
        // for using the custom view in code
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        // for using the custom view in IB
        super.init(coder: aDecoder)
        commonInit()
    }
    
    
    private func commonInit() {
        Bundle.main.loadNibNamed("CustomKeyboard", owner: self, options: nil)
        contentView.frame = self.bounds
        contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        contentView.translatesAutoresizingMaskIntoConstraints = true
        addSubview(contentView)
    }
    
    
    @IBAction func key1(_ sender: UIButton) {
    }
    
    @IBAction func key2(_ sender: UIButton) {
    }

    // etc.

    @IBAction func keyReturn(_ sender: UIButton) {
    }
    
    @IBAction func keyDelete(_ sender: UIButton) {
    }
}
  

Внутри класса CustomKeyboard я попытался:

 @IBAction func key1(_ sender: UIButton) {
    if let selectedRange: UITextRange = inputField.selectedTextRange {
        inputField.replace(selectedRange, withText: "1")
    }
}

@IBAction func keyDelete(_ sender: UIButton) {
    inputField.deleteBackward()
}
  

но, очевидно, InputField принадлежит ViewController, а не классу CustomKeyboard, поэтому я получаю сообщение об ошибке.

Итак, как мне получить символы, нажатые на пользовательской клавиатуре XIB / class, введенные в TextView в ViewController?

Комментарии:

1. Это не пользовательская клавиатура; это просто своенравный вид. Вам нужен контроллер представления ввода с inputView помощью, и вы создаете его для своего текстового представления inputView . См . developer.apple.com/design/human-interface-guidelines/ios /… и прокрутите вниз до пункта «Пользовательские виды ввода». Контроллер представления ввода автоматически подключается к текстовому представлению. См . developer.apple.com/documentation/uikit/uiinputviewcontroller

2. ОК… Где-то еще мне было предложено НЕ использовать inputView . Тем не менее, мне нравится идея его использования, если это возможно, потому что он также обеспечивает звуки щелчка, если кто-то их хочет. но я не могу понять, как использовать это в моем случае..

3. И мне не нужно расширение. Я хочу, чтобы это была единственная клавиатура, доступная в этом приложении, и ее не нужно было использовать в другом месте.

4. Да, вот почему я сказал прокрутите вниз до «Пользовательских представлений ввода». — Ну, я бы посоветовал вам начать с определения представлений ввода. Фреймворк существует именно для этой цели, так почему бы не воспользоваться им? Сделайте клавиатуру для практики, например, с одной клавишей. 🙂 Как только вы увидите, как это работает, вы сможете решить, нравится ли вам эта архитектура. Дело в том, что есть способ заменить виртуальную клавиатуру, и то, что вы делаете, это не так.

5. Вот почему я прошу помощи здесь — потому что я сам не смог разобраться. Ссылки, которые вы мне дали, отлично подходят для получения информации, но ничего не делают, чтобы показать мне, как это реализовать.

Ответ №1:

Оказывается, мне нужно было использовать только делегат. После подключения всех кнопок в XIB к keyTapped функции:

 class ViewController: UIViewController, UITextViewDelegate, KeyboardDelegate {

    @IBOutlet weak var inputField: UITextView!
    @IBOutlet weak var customKeyboard: CustomKeyboard!

    override func viewDidLoad() {
        super.viewDidLoad()

        inputField.delegate = self 
        inputField.inputView = UIView()

        customKeyboard.delegate = self     
    }

    func keyWasTapped(character: String) {        
    if character == "⌫" {
        inputField.deleteBackward()
    }
    else if character == "⏎" {
        inputField.insertText("n")
    }
    else {
        inputField.insertText(character)
    }
    
}


protocol KeyboardDelegate: class {
    func keyWasTapped(character: String)
}

class CustomKeyboard: UIView {

    weak var delegate: KeyboardDelegate?

    @IBOutlet var contentView: UIView!
    
    @IBOutlet weak var key1: UIButton!
    @IBOutlet weak var key2: UIButton!
    // etc.
    @IBOutlet weak var keyReturn: UIButton!
    @IBOutlet weak var keyDelete: UIButton!
    
    
    override init(frame: CGRect) {
        // for using the custom view in code
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        // for using the custom view in IB
        super.init(coder: aDecoder)
        commonInit()
    }
    
    
    private func commonInit() {
        Bundle.main.loadNibNamed("CustomKeyboard", owner: self, options: nil)
        contentView.frame = self.bounds
        contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        contentView.translatesAutoresizingMaskIntoConstraints = true
        addSubview(contentView)
    }
    
    @IBAction func keyTapped(sender: UIButton) {
    // When a button is tapped, send that information to the
    // delegate (ie, the view controller)
    self.delegate?.keyWasTapped(character: sender.titleLabel!.text!)
    }

    
    @IBAction func key1(_ sender: UIButton) {
    }
    
    @IBAction func key2(_ sender: UIButton) {
    }

    // etc.

    @IBAction func keyReturn(_ sender: UIButton) {
    }
    
    @IBAction func keyDelete(_ sender: UIButton) {
    }
}