【问题标题】:UINavigationController popViewControllerAnimated sluggish transitionUINavigationController popViewControllerAnimated 过渡缓慢
【发布时间】:2026-01-28 20:35:01
【问题描述】:

我有一个基于 UINavigationController 的应用程序,其中包含多个视图。

当我通过在导航控制器上调用以下方法弹出回到上一个视图控制器时,我看到了一些缓慢的过渡。我可以在我正在转换到的视图控制器的 viewWillAppear 中想到它的唯一原因是我正在做一些需要一秒钟多一点的繁重工作。在这种情况下,有什么办法可以加快过渡速度?

[self.navigationController popViewControllerAnimated:YES];

编辑: 一些重要的事情:

  1. 我正在设备上运行。
  2. 我尝试注释掉 viewWillAppear 中的所有代码,但我得到了相同的行为。
  3. 仅在 iOS 7 中观察到延迟。在 iOS 6 中尝试过,它似乎在那里工作正常。

【问题讨论】:

  • 尝试使用 Instruments 中的 Time Profiler 分析您的应用,然后返回更多

标签: ios objective-c cocoa-touch uiviewcontroller uinavigationcontroller


【解决方案1】:

我知道我参加聚会也有点晚了,但我遇到了一个非常相似的问题,我的标题图像占据了整个宽度,当弹出时它会对弹出的视图造成令人讨厌的抖动效果到。

我的解决方法很简单。我只需要确保顶层视图剪裁了它的子视图。由于我的视图是在 Interface Builder 中设计的,因此只需选择外部视图容器(带有粗边框的容器)并选中“剪辑子视图”选项。

【讨论】:

  • 谢谢,这解决了我的问题。
【解决方案2】:

如果不是来这里的 Google 员工,我可能会迟到: 如果您在离开带有花哨的 UI 内容(如全尺寸背景图像)的视图控制器时碰巧有不稳定的用户体验,请尝试添加以下内容

#import <QuartzCore/QuartzCore.h>
...
-(void)viewWillDisappear:(BOOL)animated{
    self.view.layer.shouldRasterize = YES;
    self.view.layer.rasterizationScale = [UIScreen mainScreen].scale;
}

它会使你的图层变平,因此更容易处理。

编辑: 或者如果你真的很绝望:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *fakeBackground = [[UIImageView alloc] initWithImage:snapshot];
[[self.view  subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.view addSubview:fakeBackground];

【讨论】:

    【解决方案3】:

    两件事...

    1) 你在用模拟器吗?你在经营小牛队吗?我升级时遇到了严重的性能问题。

    2) 谈到视图控制器...我尽量避免 viewWillAppear 出现。覆盖您的 init 函数并在那里进行大部分初始化。这样它就会更早地开始,并且不会在任何时候被调用。只有每次控制器出现时需要调用的东西才应该放在那里,并且该方法应该是精简的。

    【讨论】:

    • 好吧,我在设备上运行,我尝试注释掉 viewWillAppear 中的所有代码,但我得到了相同的行为。
    • 好吧,这听起来像是别的东西。就像您正在为该导航控制器分配一堆视图控制器一样。您应该只分配一次。此外,如果您有另一块代码正在异步执行任何密集的操作,则可能会影响整个应用程序。
    • 是的,你是对的。我正在初始化多个视图控制器,因为它们都在 UIScrollView 中,我们允许水平滑动它们。那么,是否有任何解决方法可以保持所需的视图控制器处于活动状态?
    • 只要您初始化并分配一次它们就不会耗尽内存。类似... self.navigationController.viewControllers = @[vc1, vc2, vc3];
    【解决方案4】:

    所以你阻塞了主线程,这就是过渡动画生涩的原因。 如果您在视图中执行的那些操作会出现与 UI 无关,请尝试在另一个线程中执行这些操作。

    如果这些操作与 UI 相关,请将计时器设置为 0.3 秒,直到过渡完成,然后在计时器触发时(动画完成后)执行与 UI 相关的操作。

    【讨论】:

    • 我尝试为我的所有 viewWillAppear 活动引入 0.3 秒的延迟,但我得到了相同的行为。