2

我有一个UINavigationController, 并从根视图控制器推送到下一个视图控制器。第二个视图控制器相当“重”,因为它有大量的初始化和子视图。

我的问题是:过渡动画的表现非常糟糕。基本上,动画的帧速率非常低(我从“推送”动画中总共得到 3-4 帧)。

我尝试了各种不同的技术,包括两种不同的手动动画过渡方法。在所有情况下,动画的前 0.4-0.7 秒都会受到这种低帧率的影响。例如,如果我将过渡时间设置为 5 秒,那么前半秒左右的效果会很差,但动画的其余部分却很流畅。

这使我相信在过渡开始时正在发生“某些事情”——导致设备以非常低的帧速率进行动画处理的事情。

在我的代码中注入了大量NSLog语句后,我看到发生了两件事。首先,显然第二个视图在推送期间被延迟加载。我通过在执行推送之前访问 view 属性上的 getter 来解决这个问题。我可以确认这会导致在推送动画开始之前发生所有初始化。

其次,我的应用程序大部分时间在转换过程中都会收到内存不足的警告。然而,即使在我没有收到内存警告的情况下,动画的表现仍然很差——让我相信这些都不是原因。

我的问题:是否有其他人在推送过渡动画中遇到过低帧率UINavigationController,但仅在动画的前 0.4-0.7 秒?幕后是否还有其他事情导致它发生,有什么可以做的吗?

作为参考,这是我当前加载并推送到下一个视图的代码。我有目的地访问视图获取器,以强制视图在转换之前加载和初始化(主要是为了排除这个问题)。此代码在主线程上执行,performSelectorOnMainThread:::以响应 Web 服务回调。

PlayingFieldViewController *v = [[PlayingFieldViewController alloc] initWithNibName:@"PlayingFieldView" bundle:[NSBundle mainBundle]];
UIView *lazy = v.view;
[appDelegate.navigationController pushViewController:v animated:YES];
[v release];

我还尝试了其他一些动画技术,结果都一样:

CATransition *transition = [CATransition animation];
transition.duration = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[appDelegate.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[appDelegate.navigationController pushViewController:v animated:NO];

和:

[UIView 
  transitionWithView:appDelegate.navigationController.view
  duration:1.0
  options:UIViewAnimationOptionTransitionCurlUp
  animations:^{
   [appDelegate.navigationController pushViewController:v animated:NO];
  }
  completion:NULL];
4

2 回答 2

4

经过进一步测试,我能够诊断出问题所在。涉及的第二种观点包括许多UIImageViews. 删除这些视图或隐藏它们可以解决问题。

让我失望的是,只有动画的第一部分存在帧速率问题,而动画的其余部分则非常流畅(在较长动画的情况下)。这向我表明,即使所有子视图都存在,该设备也能够流畅地制作过渡动画。

我仍然不是 iOS 合成方面的专家,但我猜想各个层正在被布局和缓存,导致速度变慢。解决方法是推到隐藏大部分子视图的视图,然后在视图可见时使用另一个动画显示它们。

于 2010-11-30T18:23:28.187 回答
0

我没有在导航控制器上偶然发现这一点,但是当从另一个线程更新表格视图时,我得到了大致相同的结果,UI 一开始更新速度确实很慢,但经过短暂的延迟后,一切都再次显示。正如贾斯汀在评论中指出的那样,您应该在主线程上进行 UI 工作。实现此目的的一种简单方法是将您对 UI 的调用包装在 GCD 块中:

dispatch_sync(dispatch_get_main_queue(), ^{
// Do UI stuff here
});

或使用

performSelectorOnMainThread:withObject:waitUntilDone:

于 2010-11-29T19:09:09.657 回答