开发者

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

开发者 https://www.devze.com 2023-04-13 03:57 出处:网络
I have a app in the App Store compiled for 4.2 that is acting odd when running under iOS 5.0.I have tracked it down to resignFirstResponder being called twice under iOS 5.0 while it was only being cal

I have a app in the App Store compiled for 4.2 that is acting odd when running under iOS 5.0. I have tracked it down to resignFirstResponder being called twice under iOS 5.0 while it was only being called once under iOS 4.2 & 4.3.

I have a derived a class from UITextField where I override resignFirstResponder. Se开发者_开发知识库e the sample code below.

Under iOS 4.2 & 4.3 I see the following in the console:

textFieldShouldReturn
resignFirstResponder
textFieldDidEndEditing

Under iOS 5.0 I see the following in the console:

textFieldShouldReturn
resignFirstResponder
resignFirstResponder
textFieldDidEndEditing

Running the code on the device and simulator are giving constant results. Am I missing something or is this a bug?

The 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


Below is a work around that works for iOS 4.2, 4.3, and 5.0 It is not rocket science nor sexy, but it will work until I have better understanding of what is going on (Am I doing something wrong or is this a bug?). I am reporting this as a bug to 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


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

The problem is that this disagrees with the docs -- https://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIResponder_Class/Reference/Reference.html -- so you're probably right: It's a bug.

0

精彩评论

暂无评论...
验证码 换一张
取 消