Search code examples
iosswiftuitextfield

becomeFirstResponder not called if UITextField is a subview


I am having a strange issue with UITextField:

class AnnotateTextField: UIView {

    // MARK: - Views

    let textField = UITextField()

    // MARK: - Initializers

    init() {
        super.init(frame: .zero)

        setupViews()
    }

    @available(*, unavailable)
    private override init(frame: CGRect) {
        fatalError("init(frame:) has not been implemented")
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: - Setup

    private func setupViews() {
        let textField = UITextField()
        textField.font = UIFont.systemFont(ofSize: 100.0)
        textField.textColor = .white

        backgroundColor = .black.withAlphaComponent(0.7)
        clipsToBounds = true
        layer.cornerRadius = 16.0
        // Paint stays behind it
        layer.zPosition = 1

        addSubview(textField)
        textField.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(16.0)
        }
    }

}

If I add this to my view and call becomesFirstResponder the keyboard won't show:

private func addText() {
    let annotateTextField = AnnotateTextField()

    addSubview(annotateTextField)
    annotateTextField.snp.makeConstraints { make in
        make.center.equalToSuperview()
    }

    annotateTextField.textField.becomeFirstResponder()
}

However for a regular UITextField it works fine:

private func addText() {
    let text = UITextField()
    addSubview(text)
    // This shows the keyboard
    text.becomeFirstResponder()
}

What am I doing wrong here? I tried setting user interaction enabled on AnnotateTextField and the didn't make a difference.


Solution

  • I think the promlem is in setupViews function. You are creating a new textfield object in that function and you make changes on this textfield and add it to the view.

    To solve this problem delete new texfield object inside function like :

     private func setupViews() {
    
        textField.font = UIFont.systemFont(ofSize: 100.0)
        textField.textColor = .white
    
        backgroundColor = .black.withAlphaComponent(0.7)
        clipsToBounds = true
        layer.cornerRadius = 16.0
        // Paint stays behind it
        layer.zPosition = 1
    
        addSubview(textField)
        textField.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(16.0)
        }
    }
    

    or equalizing the textfield object in the class to the object you created in this function like

     private func setupViews() {
        let textField = UITextField()
    
        textField.font = UIFont.systemFont(ofSize: 100.0)
        textField.textColor = .white
    
        backgroundColor = .black.withAlphaComponent(0.7)
        clipsToBounds = true
        layer.cornerRadius = 16.0
        // Paint stays behind it
        layer.zPosition = 1
        self.textField = textField // add this
        addSubview(self.textField) // change this
        textField.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(16.0)
        }
    }
    

    annotateTextField.textField's frame is zero because you are creating a new textfield and you are setting constraint to that textfield in function