Octavio Antonio Cedeño Octavio Antonio Cedeño - 5 months ago 18
Swift Question

Using "Next" as a Return Key

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?

Answer

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:

enter image description here

(Set up your delegate while you're here too.)


And of course, if the nextField property returns nil, the keyboard just hides.