我将从另一个UIViewController呈现一个UIViewController。呈现的视图控制器实现了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];
}
演示动画没有明显的延迟。
我的主要问题是,有没有人知道是否有另一种方法可以使文本字段成为第一响应者,而不会延迟我现在的动画?我不认为第二种解决方案是干净的。我依赖于执行选择器如何工作以获得我想要的功能的一些实现细节。我不愿意。
我也很好奇为什么第一种方法存在这样的延迟,第一种方法与第二种方法的不同之处在于“幕后”。
编辑:或许值得注意的是,当前视图控制器动画中的延迟仅在其呈现的第一时间发生。
答案 0 :(得分:3)
这是一个已知问题。看看here。
要修复它,只需将其添加到AppDelegate:
UITextField *lagFreeField = [[UITextField alloc] init];
lagFreeField.hidden = YES;
[self.window addSubview:lagFreeField];
[lagFreeField becomeFirstResponder];
[lagFreeField resignFirstResponder];
[lagFreeField removeFromSuperview];
它将在应用程序启动时加载一个不可见的键盘,它会缓存键盘并使其在后续外观(即文本视图)上加载更快。
虽然这会解决它,但它会使你的应用程序加载速度变慢(甚至可能会使你的应用程序崩溃,因为它需要很长时间)
另一个选择是将becomeFirstResponder调度到主线程,这将使其在推/模态动画完成后运行(基本上与您的第二个解决方案相同但更清洁):
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.adressTextView becomeFirstResponder];
});
我选择第二个。
无论如何要回答你的第二个问题:
延迟为0.0秒的 -performSelector:withObject:afterDelay:
不会立即执行给定的选择器,而是在当前的Runloop Cycle结束后以及在给定的延迟之后执行它。
因此,使用-performSelector:withObject:afterDelay:
UI会更改当前Runloop Cycle中的更新,即在这种情况下视图被推送,在执行选择器之前(并使textView firstResponder等等)光滑。
来源:Apple Dev Docs和this Thread Answer
希望我能帮忙。