I use the "Next" value for the "Return Key" to get the Next button in place of the Done button, but (obviously) pressing it doesn't automatically move to the next UITextField in my view.
What's the right way to do this? I have seen many answers, but anyone have a swift solution?
While on the ANSI keyboard, you can find the return key on the third row, above the right-hand Shift key and below the backslash \ key. On the ISO and JIS keyboard, the return key steps two rows on the keyboard, spanning the second and third rows, located below the BACKSPACE key and above the right-hand Shift key.
1. Alternatively known as a Return key, with a keyboard, the Enter key sends the cursor to the beginning of the next line or executes a command or operation. Most full-sized PC keyboards have two Enter keys; one above the right Shift key and another on the bottom right of the numeric keypad.
Just look at such a keyboard: the Return key says “Return”, and the Enter key says “Enter”. If your keyboard doesn't have a dedicated Enter key, you can type the Enter key by pressing Fn-Return. That's why some Return keys have “Enter” printed in small type above the word “Return”.
In a multi-line edit control on a dialog box, Ctrl + Enter inserts a carriage return into the edit control rather than executing the default button on the dialog box.
Make sure your text fields have their delegate set and implement the textFieldShouldReturn
method. This is the method that is called when the user taps the return key (no matter what it looks like).
The method might look something like this:
func textFieldShouldReturn(textField: UITextField) -> Bool { if textField == self.field1 { self.field2.becomeFirstResponder() } return true }
The actual logic in here might vary. There are numerous approaches, and I'd definitely advise against a massive if
/else
chain if you have lots of text fields, but the gist here is to determine what view is currently active in order to determine what view should become active. Once you've determined which view should become active, call that view's becomeFirstResponder
method.
For some code cleanliness, you might consider a UITextField
extension that looks something like this:
private var kAssociationKeyNextField: UInt8 = 0 extension UITextField { var nextField: UITextField? { get { return objc_getAssociatedObject(self, &kAssociationKeyNextField) as? UITextField } set(newField) { objc_setAssociatedObject(self, &kAssociationKeyNextField, newField, .OBJC_ASSOCIATION_RETAIN) } } }
And then change our textFieldShouldReturn
method to look like this:
func textFieldShouldReturn(textField: UITextField) -> Bool { textField.nextField?.becomeFirstResponder() return true }
Once you've done this, it should simply be a matter of setting each text field's new nextField
property in viewDidLoad
:
self.field1.nextField = self.field2 self.field2.nextField = self.field3 self.field3.nextField = self.field4 self.field4.nextField = self.field1
Although if we really wanted, we could prefix the property with @IBOutlet
, and that would allow us to hook up our "nextField" property right in interface builder.
Change the extension to look like this:
private var kAssociationKeyNextField: UInt8 = 0 extension UITextField { @IBOutlet var nextField: UITextField? { get { return objc_getAssociatedObject(self, &kAssociationKeyNextField) as? UITextField } set(newField) { objc_setAssociatedObject(self, &kAssociationKeyNextField, newField, .OBJC_ASSOCIATION_RETAIN) } } }
And now hook up the nextField
property in interface builder:
(Set up your delegate while you're here too.)
And of course, if the nextField
property returns nil
, the keyboard just hides.
Here is an example in Swift:
I created a screen with 6 UITextField
s. I assigned them the tags 1 through 6 in Interface Builder. I also changed the Return key to Next in IB. Then I implemented the following:
import UIKit // Make your ViewController a UITextFieldDelegate class ViewController: UIViewController, UITextFieldDelegate { // Use a dictionary to define text field order 1 goes to 2, 2 goes to 3, etc. let nextField = [1:2, 2:3, 3:4, 4:5, 5:6, 6:1] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. // Make ourselves the delegate of the text fields so that textFieldShouldReturn // will be called when the user hits the Next/Return key for i in 1...6 { if let textField = self.view.viewWithTag(i) as? UITextField { textField.delegate = self } } } // This is called when the user hits the Next/Return key func textFieldShouldReturn(textField: UITextField) -> Bool { // Consult our dictionary to find the next field if let nextTag = nextField[textField.tag] { if let nextResponder = textField.superview?.viewWithTag(nextTag) { // Have the next field become the first responder nextResponder.becomeFirstResponder() } } // Return false here to avoid Next/Return key doing anything return false } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With