presentViewController性能下降 - 取决于presentING控制器的复杂性?

Ben*_*ard 20 iphone performance cocoa-touch instruments ios

我提出了一个视图控制器:

SCAAboutController2 *controller = [[SCAAboutController2 alloc] initWithNibName:nil bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentViewController:navController animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)

在呈现之前,设备会挂起3-4秒.我试图用仪器来诊断这个,但似乎大部分时间花在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];
    });
Run Code Online (Sandbox Code Playgroud)

我很快就没有关于如何进步的想法.我如何进一步调查,和/或可能是缓慢呈现的根本原因?

编辑

一些令人困惑的发现:

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

编辑2

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

[self.browser addConstraint:[NSLayoutConstraint constraintWithItem:teamController.view
                                                         attribute:NSLayoutAttributeWidth
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:self.browser
                                                         attribute:NSLayoutAttributeWidth
                                                        multiplier:1
                                                          constant:0]];
Run Code Online (Sandbox Code Playgroud)

只有10个子控制器.同样奇怪:如果我使用以下代码,我就没有这样的问题了:

[self.browser.contentView addConstraint:[NSLayoutConstraint constraintWithItem:teamController.view
                                                                     attribute:NSLayoutAttributeWidth
                                                                     relatedBy:NSLayoutRelationEqual
                                                                        toItem:nil
                                                                     attribute:NSLayoutAttributeNotAnAttribute
                                                                    multiplier:1
                                                                      constant:200]];
Run Code Online (Sandbox Code Playgroud)

我仍然非常困惑为什么这些约束会导致另一个模态的呈现挂起,以及为什么约束的一个变体表现出与另一个不同的显着不同.

vib*_*vib 56

不确定这是原作者的问题,但这里有一些解决了类似问题的东西:我试图提供一个视图didSelectRowAtIndexPath,我之前不得不打电话deselectRowAtIndexPath.如果这可以帮助某人......

  • 只需在self.presentViewController为我修复之前添加tableView.deselectRowAtIndexPath(indexPath,animated:false).有人得到解释吗? (8认同)
  • 这也解决了我的问题,上帝只知道为什么这有任何影响.谁能解释一下? (2认同)
  • 我认为这是一个可能的解释.http://stackoverflow.com/questions/21075540/presentviewcontrolleranimatedyes-view-will-not-appear-until-user-taps-again (2认同)

Kun*_*ani 7

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

简短的ans是你有一个循环,它在一个集合中添加对象,并在主线程上执行该操作,这使得您的应用程序变慢.

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

简单的解决方案是

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  // do all the heavy lifting here in background thread. 
}

为什么以下代码没有改进任何内容:

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];
    });

因为你已经在主线程中做了这个东西,你需要在后台线程中调用main_queue.你不应该在后台线程上做任何UI的东西.


小智 5

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

            DispatchQueue.main.async {
                 Your_UI_update_function()
            }
Run Code Online (Sandbox Code Playgroud)

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