为什么UITextField在viewDidAppear中调用becomeFirstResponder会减慢当前动画的速度?

时间:2014-09-26 18:18:52

标签: ios objective-c iphone animation

我将从另一个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];
}

演示动画没有明显的延迟。

我的主要问题是,有没有人知道是否有另一种方法可以使文本字段成为第一响应者,而不会延迟我现在的动画?我不认为第二种解决方案是干净的。我依赖于执行选择器如何工作以获得我想要的功能的一些实现细节。我不愿意。

我也很好奇为什么第一种方法存在这样的延迟,第一种方法与第二种方法的不同之处在于“幕后”。

编辑:或许值得注意的是,当前视图控制器动画中的延迟仅在其呈现的第一时间发生。

1 个答案:

答案 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 Docsthis Thread Answer

希望我能帮忙。