【问题标题】:Slow performance for presentViewController - depends on complexity of presentING controller?presentViewController 性能缓慢 - 取决于呈现控制器的复杂性?
【发布时间】:2014-04-30 09:27:09
【问题描述】:

我正在展示一个视图控制器:

SCAAboutController2 *controller = [[SCAAboutController2 alloc] initWithNibName:nil bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentViewController:navController animated:YES completion:nil];

设备在演示前会挂起 3-4 秒。我曾尝试使用 Instruments 诊断此问题,但似乎大部分时间都花在 main -

这是相同的配置文件,但系统库未隐藏:

我无法识别这些消息,所以我不确定如何开始调试我的性能问题。

我在别处读到我应该检查主代码是否在主线程上执行。但是,以下更改并没有改善任何内容:

dispatch_async(dispatch_get_main_queue(), ^{
        SCAAboutController2 *controller = [[SCAAboutController2 alloc] initWithNibName:nil bundle:nil];
        UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
        [self presentViewController:navController animated:YES completion:nil];
    });

我很快就没有关于如何进步的想法了。我该如何进一步调查,和/或演示缓慢的根本原因是什么?

编辑

一些令人困惑的发现:

  • 我已经从显示的视图控制器中删除了所有代码。性能不受影响。
  • 我有另一个控制器,我通过不同的按钮从同一个地方呈现。它同样慢。
  • presentinging 控制器有很多子视图和约束 - 甚至是一些子视图控制器。删除填充这些的代码可以解决问题。
  • 在呈现控制器的viewWillDisappear 中没有添加任何内容。

编辑 2

我发现问题集中在我在主(呈现)控制器中添加的一系列布局约束上。具体来说,我遍历一些子控制器(teamController 类型)并添加约束:

[self.browser addConstraint:[NSLayoutConstraint constraintWithItem:teamController.view
                                                         attribute:NSLayoutAttributeWidth
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:self.browser
                                                         attribute:NSLayoutAttributeWidth
                                                        multiplier:1
                                                          constant:0]];

只有 10 个子控制器。也很奇怪:如果我改用以下内容,我就没有这样的问题:

[self.browser.contentView addConstraint:[NSLayoutConstraint constraintWithItem:teamController.view
                                                                     attribute:NSLayoutAttributeWidth
                                                                     relatedBy:NSLayoutRelationEqual
                                                                        toItem:nil
                                                                     attribute:NSLayoutAttributeNotAnAttribute
                                                                    multiplier:1
                                                                      constant:200]];

我仍然很困惑为什么这些约束会导致 另一个 模态的显示挂起,以及为什么一个约束的变体与另一个变体的行为截然不同。

【问题讨论】:

  • UI 总是在主线程中执行
  • NSIS* 与自动布局引擎有关。在呈现的视图控制器中会发生什么?视图是如何布局的?有多少个子视图?
  • 感谢您的提示 - 请参阅我的编辑。我有一些可以优化的布局代码,但它在当前ing 控制器中:/
  • @BenPackard 你有没有得到任何解决方案。如果是这样,请发布此问题的答案。
  • 没有有效的解决方案。

标签: ios iphone performance cocoa-touch instruments


【解决方案1】:

不确定这是原作者的问题,但这里有一个为我解决了类似问题的东西:我试图展示来自didSelectRowAtIndexPath 的视图,之前我不得不致电deselectRowAtIndexPath。如果这可以帮助某人...

【讨论】:

  • 你能再澄清一下你想说什么吗?
  • 在 self.presentViewController 之前添加 tableView.deselectRowAtIndexPath(indexPath, animated: false) 确实为我修复了它。有人解释一下吗?
  • 这也为我解决了这个问题,我有兴趣进一步解释。
  • 这也解决了我的问题,只有上帝知道这有什么影响。谁能解释一下?
  • 我认为这是一个可能的解释。 stackoverflow.com/questions/21075540/…
【解决方案2】:

您的应用由于对集合进行了多次添加和删除操作而无响应。如果您在主线程上进行任何繁重的处理,应用程序会被阻塞并变得无响应。

简短的回答是你有一个循环,它在一个集合中添加对象,它在主线程上这样做,这会让你的应用程序变慢。

如果您查看您的仪器,则视图加载按钮和渲染速度非常快。 initWithFrame , viewDidLoad 花费的时间不到总时间的 4%。大部分时间由 NSISVairable 发布和保留占用,大约完成了 500 次。所以你正在对你的集合对象做一些事情,并且可能它在一个循环中。保留和释放需要时间,不应该在主线程上完成。

简单的解决方案是:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 在后台线程中完成所有繁重的工作。 }

为什么下面的代码没有任何改进:

dispatch_async(dispatch_get_main_queue(), ^{ SCAAboutController2 *controller = [[SCAAboutController2 alloc] initWithNibName:nil bundle:nil]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller]; [self presentViewController:navController 动画:YES 完成:nil]; });

因为您已经在主线程中执行此操作,并且需要在后台线程中调用 main_queue。你不应该在后台线程上做任何 UI 的事情。

【讨论】:

  • 谢谢,我会看看我可能会操纵 NSSet 的任何地方。另请参阅我的编辑 - 我已从提供的控制器中删除了所有代码,并且性能没有提高。
  • @BenPackard 如果你添加一些 SCAAboutController2 的代码来操作数据或有循环,我会很有帮助。
  • SCAAboutController2 为空
【解决方案3】:

我遇到了类似的问题,回调位于与主线程不同的线程上。使用

            DispatchQueue.main.async {
                 Your_UI_update_function()
            }

为我解决了 UI 更新缓慢的问题。

【讨论】:

    【解决方案4】:

    添加行:

    CFRunLoopWakeUp(CFRunLoopGetCurrent());

    之后:

    [self presentViewController:navController animated:YES completion:nil];

    为我解决了这个问题。

    答案来自this thread。感谢Eugene H的评论发现。

    【讨论】:

      【解决方案5】:

      我知道我迟到了一年才发布答案。但如果它对其他人有帮助的话。

      尝试放置(快速代码)

      self.view.layer.shouldRasterize = true;
      self.view.layer.rasterizationScale = UIScreen.mainScreen().scale;
      

      对于正在呈现的视图控制器(如果它在那里不起作用,请尝试将它放在父级上。我已经把它放在两者上,它也有助于平滑所有其他动画)

      希望这会有所帮助。

      【讨论】:

      • 在 'viewWillAppear' 或 'viewDidLoad' 中添加这个?
      • 尝试在viewDidAppear中添加
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 2017-07-04
      • 2015-11-09
      相关资源
      最近更新 更多