-(BOOL)textFieldShouldReturn:(UITextField*)textField;{ NSInteger nextTag = textField.tag + 1; // Try to find next responder UIResponder* nextResponder = [textField.superview viewWithTag:nextTag]; if (nextResponder) { // Found next responder, so set it. [nextResponder becomeFirstResponder]; } else { // Not found, so remove keyboard. [textField resignFirstResponder]; } return NO; // We do not want UITextField to insert line-breaks.}
Add some more code, and the assumptions can be ignored as well.
这个方法的缺点:
This approach is fragile. You should never use magic numbers to determine anything. I realize that it's a quick and dirty fix, but a more robust solution can be had that will use less code. See my answer below. My answer will use n*4
less lines of code (n = the number of times you need to use textFieldShouldReturn
in your view controllers), is more robust, and is very easy to implement to boot.
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 (nonatomic, readwrite, assign) IBOutlet UITextField *nextField; @end
And here's the implementation:
@implementation SOTextField @synthesize nextField; @end
In your view controller, you'll create the -textFieldShouldReturn:
delegate method:
- (BOOL) textFieldShouldReturn:(UITextField *) textField { BOOL didResign = [textField resignFirstResponder]; if (!didResign) return NO; if ([textField isKindOfClass:[SOTextField class]]) dispatch_async(dispatch_get_current_queue(), ^ { [[(SOTextField *)textField nextField] becomeFirstResponder]; }); 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 looses 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.
不得不说,这2个答案下面另外2个更好,subclass那个,和textfield数组那个。