I am working on a view that has multiple UITextField
objects. My view controller serves as the UITextFieldDelegate
, and I've implemented the (BOOL)textFieldShouldEndEditing:(UITextField *)textField
method to save and validate the record being displayed.
If the user clicks on the "Done" button after editing an item and the save/validate fails, then a UIAlertView
is displayed and the user is kept on the UITextField
that fails validation.
My problem is this -- when a user clicks from the UITextField
that will fail save/validation onto another of the UITextField
s, then the (BOOL)textFieldShouldEndEditing:(UITextField *)textField
method is called multiple times, and the UIAlertView
pops up multiple times.
Why is (BOOL)textFieldShouldEndEditing:(UITextField *)textField
called once when the user clicks "Done" on the keyboard, but called multiple times when the user clicks onto another UITextField
?
Here is my code:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
NSLog(@"textFieldShouldEndEditing called by textField with text=%@", textField.text);
currentItem.nameOrNumber = nameOrNumber.text;
// Try to save the managed object.
NSError *error = nil;
if (![[currentItem managedObjectContext] save:&error]) {
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Uh Oh!",@"")
message:[error localizedDescription]
delegate:self
cancelButtonTitle:NSLocalizedString(@"OK",@"")
otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
shouldEnd = NO;
}
return shouldEnd;
}
I think your problem comes from the order in which textField methods are called when you are editing a textField and directly tap onto another.
If I am not mistaken, it should be something like this (you are editing on A and tap on B)
textFieldShouldBeginEditing
for field BtextFieldShouldEndEditing
for field AtextFieldDidEndEditing
for field AtextFieldDidBeginEditing
for field BSo when you are in textFieldShouldEndEditing
method, textfield B already has become the first responder. So when you make the UIAlertView appear, B loses focus and thus calls textFieldShouldEndEditing
too!
This also has been a problem for me when I wanted to raise a view when a textField started editing. The solution I found was to create a boolean class variable indicating whether or not I am currently switching from one textField to another.
I set it to TRUE
in textFieldShouldBeginEditing
and to FALSE
in textFieldDidBeginEditing
. When you're in textFieldShouldEndEditing
, if it is set to TRUE
it means the user directly tapped on another textField. Then you just have to find the right way to make your tests only once (maybe shouldEndEditing should return false or something).
Another option is to let the UIAlertView
fake a correct validation and defer the correcting part to a latter time. Something like this :
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
double delayInSeconds = 0.;
self.currentTextField.text = @"Something that won't trigger validation error";
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// do what you need here
});
}
Couldn't you add different tags in each textview and check the tag in the textFieldShouldEndEditing? Or have I missed the point?
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