This one is driving me a little batty and my eyes are glossing over.
I have an app with a navigation controller.
View A has some input fields and a "Continue" button which loads View B
When I tap the "Back" button on the upper left of the navigation controller its resulting in events being fired in an order I'm not expecting/understanding
My tracing reveals ...
View B: viewWillDisappear
View A: viewWillAppear
View B: textFieldShouldEndEditing
EDIT -- more detail/code explaining my previously vague question
Conceptually the following approach has been working fine, and passed several rounds of QA testing.
In summary, I'm using the textFieldShouldEndEditing
to validate textfields. If they aren't valid, I retain focus on the field and show them a message of whats wrong. All is good and validations work as the user attempts to go from field to field.
The condition that is problematic with the code below is if someone enters a partial value and then clicks BACK. All of the UITextFields
in the entire app Freeze up (don't allow input) and in some cases the app crashes.
The approach I'm attempting which led me to post the initial Question was to create a private: BOOL isDisappearing;
Which I could check in viewWillDisappear
(which in most cases fires PRIOR to textFieldShouldEndEditing), and if its YES I would short circuit the problematic code that is firing and freezing the UITextFields/app.
This is working in several views fine, but in 1 case where 'VIEW A:viewWillAppear' event fires before the textFieldShouldEndEditing
below (VIEW B) - the isDisappearing gets set to 'NO' somehow and the problematic code is firing in textFieldShouldEndEditing
I hope this helps and you can follow. I find it hard to explain without code – but I've tried to trim it down to just what is relevant. I hope this is appropriate here – I'm pretty new to the community.
Code for VIEW B:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)rangereplacementString:(NSString *)string
{
// Enforce max lengths
// The return key from the keyboard counts as a character, so we have to exempt it
if (textField.tag == ROUTING_NUMBER_TAG)
{
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 9 && ![string isEqualToString:@"\n"]) ? NO : YES;
}
else if (textField.tag == ACCOUNT_NUMBER_TAG)
{
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 17 && ![string isEqualToString:@"\n"]) ? NO : YES;
}
return YES;
}
// textField validation
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
if (isDisappearing)
return YES;
//run fields through validators and display validation messages.
//IF THEY DON’T PASS VALIDATION IM "HOLDING THEM HOSTAGE" BY KEEPING THE FOCUS ON THE UITEXTFIELD (returning NO)
if (textField.tag == ROUTING_NUMBER_TAG )
{
if ([Utility isValidRoutingNumber:textField.text]== NO)
{
[[iToast makeText:NSLocalizedString(@"Enter valid routing number", @"")] show];
return NO;
}
else
{ //save it
extension.payment.routingNumber = routingNumber.text;
}
}
else if (textField.tag == ACCOUNT_NUMBER_TAG)
{
if ([Utility isValidAccountNumber:textField.text] == NO)
{
[[iToast makeText:NSLocalizedString(@"Enter valid account number", @"")] show];
return NO;
}
else
{ //save it
extension.payment.accountNumber = accountNumber.text;
}
}
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
//I do nothing here except nulling out the 'activefield' var I use to autoscroll the uiscrollview as the user taps around from field to field
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//reset the bool so that when they come back we're back to the 'normal' state and validation will again be checked in textFieldShouldEndEditing
isDisappearing = NO;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
-(void)viewWillDisappear:(BOOL)animated
{
TRC_ENTRY
//set the bool to bypass validations in textFieldShouldEndEditing
isDisappearing = YES;
[super viewWillDisappear:animated];
}