【问题标题】:Why is resignFirstResponder being called twice in iOS 5.0 but only once in iOS4.2-4.3?为什么在 iOS 5.0 中 resignFirstResponder 被调用了两次,而在 iOS4.2-4.3 中只调用了一次?
【发布时间】:2011-12-06 15:19:52
【问题描述】:

我在 App Store 中有一个为 4.2 编译的应用,它在 iOS 5.0 下运行时表现异常。我已经追踪到 resignFirstResponder 在 iOS 5.0 下被调用了两次,而在 iOS 4.2 和 4.3 下它只被调用了一次。

我有一个从UITextField 派生的类,我在其中覆盖resignFirstResponder。请参阅下面的示例代码。

在 iOS 4.2 和 4.3 下,我在控制台中看到以下内容:

textFieldShouldReturn
resignFirstResponder
textFieldDidEndEditing

在 iOS 5.0 下,我在控制台中看到以下内容:

textFieldShouldReturn
resignFirstResponder
resignFirstResponder
textFieldDidEndEditing

在设备和模拟器上运行代码会给出恒定的结果。我错过了什么还是这是一个错误?

iOS 5.0 堆栈跟踪

#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

【问题讨论】:

    标签: ios uitextfield ios5 resignfirstresponder


    【解决方案1】:

    以下是适用于 iOS 4.2、4.3 和 5.0 的解决方法。它既不是火箭科学也不是性感的,但在我更好地了解正在发生的事情之前它会起作用(我做错了什么或者这是漏洞?)。我将此作为错误报告给 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
    

    【讨论】:

    • 附注,有没有办法查看其他人的 Apple 错误报告?
    • 谢谢,这对我帮助很大!
    【解决方案2】:

    一种解决方案是改写canResignFirstResponder。这只会被调用一次。

    问题在于这与文档不一致——https://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIResponder_Class/Reference/Reference.html——所以你可能是对的:这是一个错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-20
      • 2019-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-22
      • 1970-01-01
      相关资源
      最近更新 更多