0
votes

I've been stuck on this problem for a little while.

I have an inputAccessoryView I want to use for my keyboard, and the inputAccessoryView has a UITextField in it. This is the text field that should be activating the keyboard, but can't because it exists in the inputAccessoryView.

I have a 2nd UITextField added to the hosting view via the view controller's viewDidLoad. This 2nd UITextField is hidden off and is just a means for activating the keyboard via becomeFirstResponder.

I have a delegate set up for my custom inputAccessoryView that gets called when the user dismisses the keyboard belonging to the text field existing in the accessory view. I have code in this delegate function to also resignFirstResponder on the 2nd, hidden keyboard. This works fine and dandy.

What I am currently having problems with is getting similar behaviour for when becomingFirstResponder. I want to make it so when the hidden keyboard becomes first responder it immediately calls first responder on the 2nd keyboard within the accessory view, make it seem like its just being activated in the first place.

I'm unsure how to achieve this. I tried implementing UITextField's delegate on my view controller and overriding textFieldDidBeginEditing and making the becomeFirstResponder call in there, but to no avail.

Any explanations as to why this isn't working, or other approaches to take?

Edit: I've followed the advice here. It does allow the first responder ownership to transfer, but is a bit jerky in doing so (previous keyboard still shows for a split second) and now the resignFirstResponder process which previously worked nicely doesn't work at all. I guess the textFieldDidBeginEditing is getting triggered during the resignFirstResponder call and is calling becomeFirstResponder again. I now cannot dismiss the keyboard.

1

1 Answers

0
votes

After starting a new, empty project and poking around for a bit, I came up with the following solution, which seems to be working nicely and as expected, so far.

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!
    var accessory: CustomView!
    var denyFirstResponder = false
    var dismissTap: UITapGestureRecognizer!

    override func viewDidLoad() {
        super.viewDidLoad()
        accessory = CustomView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 44))
        textField.inputAccessoryView = accessory
        textField.delegate = self
        dismissTap = UITapGestureRecognizer(target: self, action: #selector(shouldDismiss))
        view.addGestureRecognizer(dismissTap)
    }

    func shouldDismiss(_ recognizer: UITapGestureRecognizer) {
        accessory.textField.resignFirstResponder()
    }

    @IBAction func buttonPressed(_ sender: UIButton) {
        textField.becomeFirstResponder()
    }

    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        if denyFirstResponder {
            denyFirstResponder = false
            return false
        }
        return true
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        denyFirstResponder = true
        accessory.textField.perform(#selector(becomeFirstResponder), with: nil, afterDelay: 0)
    }

}

class CustomView: UIView {

    var textField: UITextField!

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor.blue
        textField = UITextField(frame: CGRect(x: 10, y: 10, width: frame.width - 20, height: 24))
        addSubview(textField)
        textField.keyboardType = .decimalPad
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

}