There is a much more elegant solution which blew me away the first time I saw it. Benefits:
- Closer to OSX textfield implementation where a textfield knows where the focus should go next
- Does not rely on setting or using tags -- which are, IMO fragile for this use case
- Can be extended to work with both
UITextField
and UITextView
controls -- or any keyboard entry UI control
- Doesn't clutter your view controller with boilerplate UITextField delegate code
- Integrates nicely with IB and can be configured through the familiar option-drag-drop to connect outlets.
Create a UITextField subclass which has an IBOutlet
property called nextField. Here's the header:
@interface SOTextField : UITextField
@property (weak, nonatomic) IBOutlet UITextField *nextField;
@end
And here's the implementation:
@implementation SOTextField
@end
In your view controller, you'll create the -textFieldShouldReturn:
delegate method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ([textField isKindOfClass:[SOTextField class]]) {
UITextField *nextField = [(SOTextField *)textField nextField];
if (nextField) {
dispatch_async(dispatch_get_current_queue(), ^{
[nextField becomeFirstResponder];
});
}
else {
[textField resignFirstResponder];
}
}
return YES;
}
In IB, change your UITextFields to use the SOTextField
class. Next, also in IB, set the delegate for each of the 'SOTextFields'to 'File's Owner' (which is right where you put the code for the delegate method - textFieldShouldReturn). The beauty of this design is that now you can simply right-click on any textField and assign the nextField outlet to the next SOTextField
object you want to be the next responder.
Moreover, you can do cool things like loop the textFields so that after the last one loses focus, the first one will receive focus again.
This can easily be extended to automatically assign the returnKeyType
of the SOTextField
to a UIReturnKeyNext
if there is a nextField assigned -- one less thing manually configure.