becomeFirstResponder 在 ios 11 中不显示键盘

Posted

技术标签:

【中文标题】becomeFirstResponder 在 ios 11 中不显示键盘【英文标题】:becomeFirstResponder not show keyboard in ios 11 【发布时间】:2018-05-27 15:08:08 【问题描述】:

我试图在加载屏幕后显示一个键盘,如下所示:

 -(void) viewDidAppear:(BOOL)animated 
     [super viewDidAppear:animated];
     UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(10, 200, 300, 40)];
     tf.borderStyle = UITextBorderStyleRoundedRect;
     tf.text = @"test";

    [self.view addSubview:tf]; 
    if([tf canBecomeFirstResponder])
        [tf becomeFirstResponder]; // surely this line is called          
     
 

此代码适用于 ios 8、9、10,但不适用于 11。我不确定为什么在文本字段聚焦(有光标)时键盘不会在 ios 11 上自动显示。 在这种情况下,不会调用键盘的通知:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

- (void) keyboardWillShow:(NSNotification *)note 
    NSDictionary *userInfo = [note userInfo];
    CGSize kbSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    DLog(@"Keyboard Height: %f Width: %f", kbSize.height, kbSize.width);
 

我什至试试这个:

[tf performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0]; 

但还是不行。

我必须点击文本字段才能调出键盘。 Apple 有什么我不知道的更新吗?

更新:我的项目或所有视图控制器似乎有问题,因为我无法让键盘显示在所有屏幕上。但是当我用上面的代码创建新项目时,它可以很好地工作。 这是问题之一:

如您所见,我必须单击文本字段才能显示键盘,并且从第二次开始,它可以正常工作。而且这个问题只发生在 ios 11(模拟器和设备) 这是上面搜索字段的代码:

    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 215, 30)];
    textField.backgroundColor = [UIColor clearColor];
    textField.placeholder = @"Enter text to search";
    textField.borderStyle = UITextBorderStyleLine;
    textField.layer.masksToBounds=YES;
    textField.layer.borderColor=[[UIColor lightGrayColor]CGColor];
    textField.layer.borderWidth= 1.0f;
    textField.returnKeyType = UIReturnKeySearch;
    textField.delegate = self;
    textField.clearButtonMode = UITextFieldViewModeAlways;
    [UIView transitionWithView:self.navigationController.navigationBar
                  duration:0.55f
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^
                    self.navigationItem.titleView = textField;
                 completion:^(BOOL finished) 
                    [textField becomeFirstResponder];
                ];

不知道有没有什么东西会导致键盘冲突?

【问题讨论】:

你在模拟器上运行你的代码??如果是,通过选择模拟器切换硬件键盘,然后点击 command+shift+k 为什么要在viewDidAppear 方法中添加文本字段?可以多次调用。您应该在viewDidLoad 中添加文本字段。您仍然可以使其成为viewDidAppear 中的第一响应者。 @SandeepBhandari 我在设备和模拟器上都进行了测试。我已经使用切换键盘。如果我手动单击文本字段,键盘可以正确显示,但我想在屏幕加载后自动显示 @rmaddy 我知道,这是我尝试测试的唯一方法,以确保屏幕已加载。正如你所说,我只是在 viewdidload 中添加视图并在 viewDidAppear 中设置第一响应者,但仍然无法正常工作,键盘没有显示 @R4 thanx 但我解决了问题。我的应用程序中有 2 个窗口,并将 makeKeyAndVisible 设置为另一个窗口。那位裁判帮助了我developer.apple.com/library/content/qa/qa1813/_index.html 【参考方案1】:

当尚未在屏幕上绘制 TextField 时,becomeFirstResponder() 将不起作用。例如,当它被隐藏并且从未绘制时。然后你需要在它被绘制之后调用 becomeFirstResponder() 。也许这会有所帮助:

DispatchQueue.main.async 
    tf.becomeFirstResponder()

【讨论】:

【参考方案2】:

我创建了一个新项目并尝试了您的代码。它在模拟器和设备 iOS11 上都能正常工作。显示键盘并调用通知。这是我尝试过的代码。

@implementation ViewController

- (void)viewDidLoad 
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.

  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(keyboardWillShow:)
                                               name:UIKeyboardWillShowNotification
                                             object:nil];


- (void)viewDidAppear:(BOOL)animated 
  [super viewDidAppear:animated];
  UITextField* tf = [[UITextField alloc] initWithFrame:CGRectMake(10, 200, 300, 40)];
  tf.borderStyle = UITextBorderStyleRoundedRect;
  tf.text = @"test";

  [self.view addSubview:tf];
  if ([tf canBecomeFirstResponder]) 
    [tf becomeFirstResponder];  // surely this line is called
  


- (void)keyboardWillShow:(NSNotification*)note 
  NSDictionary* userInfo = [note userInfo];
  CGSize kbSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

  NSLog(@"Keyboard Height: %f Width: %f", kbSize.height, kbSize.width);


@end

您应该检查DLog 方法。我认为键盘的通知被调用,但由于DLog 方法没有记录任何内容。

【讨论】:

我已经运行调试,而不仅仅是日志。而keyboardWillShow 仅在我单击 UITextField 以强制显示键盘时被调用。键盘是否总是显示在您身边而不触摸文本字段? 当我检查时,键盘总是显示在模拟器和设备上。你可以在这里看到它media.giphy.com/media/3ohjUUSFCXvimPR7l6/giphy.gif 谢谢。当我使用上述代码创建新项目时,它可以工作。我在视图控制器中的其他代码有问题 很好的答案!我想为其他人补充说,用户在 viewDidAppear 中正确使用了“becomeFirstResponder”。例如,如果您在 viewWillAppear 中使用“becomeFirstResponder”,那么如果该视图尚未添加到视图层次结构中,则 canBecomeFirstResponder 可能会返回 false。您可以保证它已添加到 viewDidLoad 中的视图层次结构中,但我认为(可能是错误的)将“canBecomeFirstResponder”放入 viewDidAppear 可确保也添加了观察者(我在 viewDidLoad 中遇到了观察者问题)。跨度> 【参考方案3】:

试试这个。我觉得 textField 对象在完成块中为空,而您在此调用 becomeFirstResponder

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 215, 30)];
textField.backgroundColor = [UIColor clearColor];
textField.placeholder = @"Enter text to search";
textField.borderStyle = UITextBorderStyleLine;
textField.layer.masksToBounds=YES;
textField.layer.borderColor=[[UIColor lightGrayColor]CGColor];
textField.layer.borderWidth= 1.0f;
textField.returnKeyType = UIReturnKeySearch;
textField.delegate = self;
textField.clearButtonMode = UITextFieldViewModeAlways;
[UIView transitionWithView:self.navigationController.navigationBar
              duration:0.55f
               options:UIViewAnimationOptionTransitionCrossDissolve
            animations:^
                self.navigationItem.titleView = textField;
             completion:^(BOOL finished) 
                [((UITextField *)self.navigationItem.titleView) becomeFirstResponder];
            ];

【讨论】:

【参考方案4】:

试试这个;

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField 
    [theTextField resignFirstResponder];
    return NO;


- (void)viewWillAppear:(BOOL)animated 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];



- (void)keyboardWillShow:(NSNotification *)notification 
        CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;


- (void)keyboardWillHide:(NSNotification *)notification 


【讨论】:

我试过这个。问题是键盘不显示,所以通知不起作用。只有当我点击文本字段时它才能工作【参考方案5】:

在我的情况下,问题是,我有 2 个UIWindow 对象,而我用来添加 UI 元素的对象没有设置为键窗口,并且键盘窗口的级别较低,因此键盘被我的另一个窗口覆盖。我只需要在第二个窗口上拨打makeKeyAndVisible()。 john07 的评论帮助我解决了这个问题。如需进一步参考检查:https://developer.apple.com/library/archive/qa/qa1813/_index.html

【讨论】:

【参考方案6】:

真的很奇怪,因为这个问题可以在显示UIAlertView后修复 因此,当我尝试在显示带有上述代码的键盘之前添加带有加载指示器的UIAlertView(并在几秒钟后自动关闭),如this,它可以正常工作。 不知道我的项目的根本原因,但它确实有效。 而且它只发生在 ios 11 上。

【讨论】:

以上是关于becomeFirstResponder 在 ios 11 中不显示键盘的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 6 中,-[UITextField becomeFirstResponder] 在 -viewWillAppear 中不起作用:

IOS 获取文本焦点 主动召唤出键盘(becomeFirstResponder)

UITextView becomeFirstResponder 使用 iOS SDK 8.2 失败

becomeFirstResponder 第二次不显示键盘(ios 6 + 故事板)

ios8 UIAlertView becomeFirstResponder for Password UITextField 不起作用

Xcode 9.3.1 - iOS Swift 4.1 UITextView.becomeFirstResponder 线程 1:EXC_BAD_ACCESS(代码=1,地址=0x4d555458)