Ios textFieldDidBeginEditing被过早地调用

Ios textFieldDidBeginEditing被过早地调用,ios,uitextfield,autoscroll,uitextfielddelegate,Ios,Uitextfield,Autoscroll,Uitextfielddelegate,我有一个应用程序,在其中我必须向上滚动以防键盘显示。 为了获得键盘大小,我注册了UIKeyboardWillShowNotification事件,如下所示: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.wi

我有一个应用程序,在其中我必须向上滚动以防键盘显示。 为了获得键盘大小,我注册了UIKeyboardWillShowNotification事件,如下所示:

   [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(keyboardWillShow:)
     name:UIKeyboardWillShowNotification
     object:self.view.window]
这是可行的,问题是,它是在调用textfielddebeginediting后调用的。因此,我无法获得实际的键盘大小,但只能在字段已经处于编辑模式之后,这就违背了注册此事件的全部目的。 我确信我调用了UIKeyboardWillShowNotification,而不是UIKeyboardDidShowNotification,尽管切换这两个会产生相同的结果:
首先调用委托方法,然后才调用通知方法。你知道如何扭转这种局面吗?目前我正在硬编码大小,这是一种非常糟糕的做法…

我在XCode 5中打开了一个新项目,在
视图控制器中添加了一个
UITextField
,并连接了它的代理

这是我唯一的代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myNotificationMethod:) name:UIKeyboardWillShowNotification object:nil];
}

- (void)myNotificationMethod:(NSNotification*)notification
{
    NSDictionary* keyboardInfo = [notification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
    NSLog(@"Rect: %@",NSStringFromCGRect(keyboardFrameBeginRect));
}
以下是日志输出:

Portraid:

 Rect: {{0, 480}, {320, 216}}
 Rect: {{-162, 0}, {162, 480}}
景观:

 Rect: {{0, 480}, {320, 216}}
 Rect: {{-162, 0}, {162, 480}}
编辑:

 Rect: {{0, 480}, {320, 216}}
 Rect: {{-162, 0}, {162, 480}}
关于在
name:UIKeyboardWillShowNotification
之前调用
textfieldDiBeginediting
,我真的不明白为什么textField是否处于编辑模式会有区别,但有几种方法可以解决这个问题

  • 从textFieldShouldBeginEditing保存对textField的引用,如果触发了in-did textFieldShouldBeginEditing,则在myNotificationMethod中使用该引用

  • 玩弄
    ui应答器
    就像这样:


  • textfieldDiBeginediting
    ->中,保存对
    UIResponder
    的引用,并将
    UIResponder
    更改为临时无关的引用。在
    myNotificationMethod
    中,对文本字段(不在编辑模式下的\first responder)执行任何您想执行的操作,完成后将其设置为主
    UIResponder

    这是我为这个用途编写的一个基类。它是
    UIViewController
    每当我想要实现这样的行为时,我就把我的视图控制器作为这个基类的一个子类

    顺便说一句,你是对的
    textFieldDidBeginEditing
    在键盘显示后被调用,这就是为什么您希望在键盘的Callbacks方法中向上滚动,如我的课程中所述

    另外,请注意,要使其工作,您需要将整个视图嵌入到滚动视图中,并将滚动视图的IBOutlet连接到该视图

    如果您不使用故事板,请删除IBOutlet部分,并将视图嵌入到滚动视图中,并在代码中建立连接

    这之后是代码:

    头文件

    #import <UIKit/UIKit.h>
    
    @interface BaseViewControllerWithKeyboard : BaseViewController
    
    @property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
    @property (nonatomic, strong) UITextField *activeField;
    
    @end
    
    #import "BaseViewControllerWithKeyboard.h"
    
    @interface BaseViewControllerWithKeyboard ()
    
    @end
    
    @implementation BaseViewControllerWithKeyboard
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self registerForKeyboardNotifications];
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    // Call this method somewhere in your view controller setup code.
    - (void)registerForKeyboardNotifications
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWasShown:)
                                                     name:UIKeyboardDidShowNotification object:nil];
    
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillBeHidden:)
                                                     name:UIKeyboardWillHideNotification object:nil];
    
    }
    
    // Called when the UIKeyboardDidShowNotification is sent.
    - (void)keyboardWasShown:(NSNotification*)aNotification
    {
        NSDictionary* info = [aNotification userInfo];
        CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
        _scrollView.contentInset = contentInsets;
        _scrollView.scrollIndicatorInsets = contentInsets;
    
        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your app might not need or want this behavior.
        CGRect aRect = self.view.frame;
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, _activeField.frame.origin) ) {
            [self.scrollView scrollRectToVisible:_activeField.frame animated:YES];
        }
    }
    
    // Called when the UIKeyboardWillHideNotification is sent
    - (void)keyboardWillBeHidden:(NSNotification*)aNotification
    {
        UIEdgeInsets contentInsets = UIEdgeInsetsZero;
        _scrollView.contentInset = contentInsets;
        _scrollView.scrollIndicatorInsets = contentInsets;
    }
    
    @end
    

    根据苹果的文档,UIKeyboardWillShowNotification在显示键盘之前调用,而UIExtFieldDidBeginediting在文本字段成为第一响应者之后调用。显示键盘的过程在文本字段成为第一响应者后开始,并且仅当键盘尚未显示时。这意味着UIKeyboardWillShowNotification将在UIExtFieldDidBeginediting之后调用。因此,uitextfielddibeginediting不会过早调用


    如果您只想向上滚动,这样文本字段就不会隐藏在键盘下,您可以在uitextfield shouldbegineditinguitextfield didbeginediting中将滚动视图的内容偏移设置为文本字段的y原点

    我可以推荐一个GitHub存储库吗


    老问题,但我今天遇到了同样的问题。我已经建立了一个小的“肮脏”的解决办法,不强迫我硬编码键盘大小。我只是在ViewDidEmerge中做了以下操作(注意-Swift):


    这将触发UIKeyboardWillShowNotification,您可以从通知中获取键盘大小并将其存储在属性中。希望这对其他人有所帮助,在我的情况下它起到了作用。

    你有解决方案吗?我也在处理这个问题。.我假设当键盘通知触发时,你需要知道哪个UITextField正在被编辑,以便你可以正确滚动,这是正确的吗?如果是这样的话,那么您可以在
    textViewDidBeginEditing
    中隐藏对该UITextField的引用,以便在收到通知时使用。这很酷,问题是,如果您使用textfield:didBeginEditing:method,您可以看到它在键盘通知发出之前被调用。@Rizon从
    textfield shouldbeginediting
    保存对
    textfield
    的引用,并在
    myNotificationMethod
    中使用它怎么样是否被触发?我不知道为什么文本字段是否处于编辑模式会有差异。更多地解释一下你为什么要这样做可能会有所帮助。请查看这个解决方案@RizonA用例,它回避了这个代码。。。1.如果UIView有多个UITextFields和2。只有一部分字段需要滚动视图3。然后,当用户将焦点从一个UITextfield移动到另一个UITextfield时,4。键盘显示:将不被调用。1。为什么它不能处理多个文本字段?它有两个。请解释一下。儿子,在这种情况下也没什么问题。4.如果您正确注册通知,KeyboardwasShowed将被调用。例如,1。用户首先点击UITextField,键盘显示:被调用。2.键盘被显示,UIView被稍微滚动3下。用户点击第二个UITextBox(假设键盘与此框的下部重叠,但用户仍可以点击它)4。键盘是可见的,因此KeyboardwasShow:未调用。我添加了一个textFieldDidBeginEditing的处理程序:如果