Why is resignFirstResponder called twice in iOS 5.0, but only once in iOS4.2-4.3?

I have an app in the App Store compiled for 4.2 that runs odd when running under iOS 5.0. I traced it to resignFirstResponder , which was called twice under iOS 5.0, while it was called once under iOS 4.2 and 4.3.

I have a derived class from UITextField where I override resignFirstResponder . See the sample code below.

In iOS 4.2 and 4.3, I see the following in the console:

 textFieldShouldReturn resignFirstResponder textFieldDidEndEditing 

In iOS 5.0, I see the following on the console:

 textFieldShouldReturn resignFirstResponder resignFirstResponder textFieldDidEndEditing 

Running code on the device and the simulator gives consistent results. Am I missing something or is this a mistake?

IOS 5.0 stack trace

 #0 -[BugTextField resignFirstResponder] (self=0x681b530, _cmd=0x3769b41) at /Users/.../BugTextField.m:14 #1 0x006c05a6 in -[UIFieldEditor resignFirstResponder] () #2 0x006374e3 in -[UIView(Hierarchy) _willMoveToWindow:] () #3 0x006362c2 in __UIViewWillBeRemovedFromSuperview () #4 0x006360d7 in -[UIView(Hierarchy) removeFromSuperview] () #5 0x006bfff7 in -[UIFieldEditor becomeFieldEditorForView:] () #6 0x006ae37b in -[UITextField _resignFirstResponder] () #7 0x006eb8d4 in -[UIResponder _finishResignFirstResponder] () #8 0x006eba20 in -[UIResponder resignFirstResponder] () #9 0x006ae249 in -[UITextField resignFirstResponder] () #10 0x00017f68 in -[BugTextField resignFirstResponder] (self=0x681b530, _cmd=0x3769b41) at /Users/.../BugTextField.m:16 #11 0x0001828f in -[BugTextFieldVC textFieldShouldReturn:] (self=0x6829750, _cmd=0x18c5b, textField=0x681b530) at /Users/.../BugTextFieldVC.m:40 

BugTextField.h

 #import <UIKit/UIKit.h> @interface BugTextField : UITextField @end 

BugTextField.m

 #import "BugTextField.h" @implementation BugTextField - (BOOL) resignFirstResponder { NSLog(@"resignFirstResponder"); return [super resignFirstResponder]; } @end 

BugTextFieldVC.h

 #import <UIKit/UIKit.h> @class BugTextField; @interface BugTextFieldVC : UIViewController <UITextFieldDelegate> { BugTextField *bugTextField; } @end 

BugTextFieldVC.m

 #import "BugTextFieldVC.h" #import "BugTextField.h" @implementation BugTextFieldVC - (id) init { if ( !(self = [super init]) ) { return self; } // One text field with 100 height keyboard bugTextField = [[BugTextField alloc] initWithFrame:CGRectMake(10, 10, 300, 30)]; bugTextField.borderStyle = UITextBorderStyleRoundedRect; bugTextField.delegate = self; [self.view addSubview:bugTextField]; return self; } - (void) dealloc { [bugTextField release]; [super dealloc]; } - (BOOL) textFieldShouldReturn:(UITextField *)textField { NSLog(@"textFieldShouldReturn"); [textField resignFirstResponder]; return YES; } - (void) textFieldDidEndEditing:(UITextField *)textField { NSLog(@"textFieldDidEndEditing"); } @end 
+7
source share
2 answers

Below is a job that works for iOS 4.2, 4.3 and 5.0. This is not rocket science or sexuality, but it will work until I get a better understanding of what is happening (am I doing something wrong or is it a mistake?). I report this as an error for Apple.

BugTextField.h

 #import <UIKit/UIKit.h> @interface BugTextField : UITextField { // Value used to ensure code in resignFirstResponder is executed by the // first stack frame and not subsequent stack frames in iOS 5.0. // // In iOS 5.0, one call to resignFirstResponder results in a second call to // resignFirstResponder. In iOS 4.2 & 4.3, one call to resignFirstResponder // does not result in subsequent calls to resignFirstResponder. NSUInteger resignFirstResponderCallDepth; } @end 

BugTextField.m

 #import "BugTextField.h" @implementation BugTextField - (BOOL) resignFirstResponder { if (0 == resignFirstResponderCallDepth++) { // --------------------------------------------------------------------- // Code executed by first stack frame to call resignFirstResponder. NSLog(@"resignFirstResponder"); } // ------------------------------------------------------------------------- // Code executed by every stack frame to call resignFirstResponder. BOOL rV = [super resignFirstResponder]; resignFirstResponderCallDepth--; return rV; } @end 
+1
source

One solution is to override canResignFirstResponder . This will only be called once.

The problem is that this is not consistent with the docs - https://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIResponder_Class/Reference/Reference.html - so you're probably right: this mistake.

0
source

All Articles