我正在展示另一个 UIViewController 的 UIViewController。呈现的 View Controller 这样实现 viewDidAppear:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.addressTextView becomeFirstResponder];
}
但是,如果我这样实现 viewDidAppear:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.addressTextView performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.0f];
}
演示动画没有明显的延迟。
我的主要问题是,有没有人知道是否有另一种方法可以让文本字段成为第一响应者,而不会延迟我当前的动画?我不认为第二种解决方案是干净的。我依靠执行选择器如何工作的一些实现细节来获得我想要的功能。我宁愿不要。
我也很好奇为什么第一种方法会有这样的延迟,以及第一种方法与第二种方法“在幕后”有何不同。
编辑:可能值得注意的是,当前 View Controller 动画中的延迟仅在第一次呈现时发生。
最佳答案
这是一个已知问题。看看here .
要修复它,只需将其添加到您的 AppDelegate 中:
UITextField *lagFreeField = [[UITextField alloc] init];
lagFreeField.hidden = YES;
[self.window addSubview:lagFreeField];
[lagFreeField becomeFirstResponder];
[lagFreeField resignFirstResponder];
[lagFreeField removeFromSuperview];
它将在应用程序启动时加载一个不可见的键盘,它缓存键盘并使其在后续出现时加载速度更快,即您的 TextView 。
虽然这会修复它,但它会使您的应用程序加载速度变慢(甚至可能使您的应用程序崩溃,因为它需要很长时间)
另一种选择是将 becomeFirstResponder 分派(dispatch)到主线程,这将使其在推送/模态动画完成后运行(与您的第二个解决方案基本相同,但更简洁):
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.adressTextView becomeFirstResponder];
});
我会选择第二个。
无论如何回答你的第二个问题:
-performSelector:withObject:afterDelay:
延迟 0.0 秒不会立即执行给定的选择器,而是在当前 Runloop 循环完成后和给定的延迟后执行。
因此使用 -performSelector:withObject:afterDelay:
UI 会在当前 Runloop Cycle 中发生更新,即在这种情况下,在执行选择器之前推送 View (并使您的textView firstResponder 等等),这让一切变得顺利。
来源:Apple Dev Docs和 this Thread Answer
希望我能帮上忙。
关于ios - 为什么 UITextField 在 viewDidAppear 中调用 becomeFirstResponder 会减慢当前动画的速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26065908/