How to disable/enable the return key in a UITextField?

Viewed 62802

Is there a way to programmatically enable or disable the Return Key on the UIKeyboard? The closest I could find is enablesReturnKeyAutomatically, but that only will tell whether to disable it at all.

8 Answers

Let me suggest a bit hacky solution which requires no subclassing.

extension UITextFieldDelegate {
    func setReturnKeyState(for textField: UITextField, isEnabled: Bool, delay: Double? = nil) {
        textField.enablesReturnKeyAutomatically = false
        if textField.delegate != nil {
            if let delay = delay {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                    textField.setValue(isEnabled, forKeyPath: "inputDelegate.returnKeyEnabled")
                }
            } else {
                textField.setValue(isEnabled, forKeyPath: "inputDelegate.returnKeyEnabled")
            }
        }
    }
}

Usage practical sample

Define any condition, for example like this:

private func validateInput(_ string: String?) -> Bool {
    (string?.count ?? 0) > 3
}

Call setReturnKeyState in delegate methods, for example:

func textFieldDidBeginEditing(_ textField: UITextField) {
    setReturnKeyState(for: textField, isEnabled: validateInput(textField.text), delay: 0.1) // A bit hacky it needs delay here
}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if var text = textField.text, let range = Range(range, in: text) {
        text.replaceSubrange(range, with: string)
        setReturnKeyState(for: textField, isEnabled: validateInput(text))
    }
    return true
}

My answer to the duplicate question, copied over:

All the other solutions do not answer the question. OP wants to "gray" out the return button on the keyboard as a visual signal to the user.

Here is my solution, working on iOS 13. You may have to modify the solution slightly for other iOS versions.

First, I extend UITextFieldDelegate.

func getKeyboard() -> UIView?
    {
        for window in UIApplication.shared.windows.reversed()
        {
            if window.debugDescription.contains("UIRemoteKeyboardWindow") {
                if let inputView = window.subviews
                    .first? // UIInputSetContainerView
                    .subviews
                    .first // UIInputSetHostView
                {
                    for view in inputView.subviews {
                        if view.debugDescription.contains("_UIKBCompatInputView"), let keyboard = view.subviews.first, keyboard.debugDescription.contains( "UIKeyboardAutomatic") {
                            return keyboard
                        }
                    }
                }
                
            }
        }
        return nil
    }

Then, whenever I need to disable the "return" key, we can do (replace delegate with the variable name of your delegate object):

if let keyboard = delegate.getKeyboard(){
    keyboard.setValue(text == nil, forKey: "returnKeyEnabled")
}

Here is a technique that is available from the documented API, but it does not provide visual feedback when the enter key is disabled.

- (void)setup {
    // Or in init
    self.textField.delegate = self;
}

// <UITextFieldDelegate>
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    // substitute your test here
    return [textField.text rangeOfString:@"@"].location != NSNotFound;
}

Other answers here can be used with

[textField addTarget:self
              action:@selector(validateTextField:)
    forControlEvents:UIControlEventEditingChanged];

to provide dynamic visual feedback as the user types.

Try to use a UITextField! to receive this string and than the return are gone!

Related