Медленная производительность для presentViewController - зависит от сложности представления контроллера?

Я представляю контроллер вида:

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

Устройство отображается в течение 3-4 секунд перед представлением. Я попытался диагностировать это с помощью инструментов, но, похоже, большая часть времени проведена в main -

enter image description here

Вот такой же профиль, но с системными библиотеками:

enter image description here

Ни одно из этих сообщений не распознается мне, поэтому я не уверен, как начать отладку моей проблемы с производительностью.

Я читал в другом месте, что я должен проверить, что основной код выполняется в основном потоке. Однако следующее изменение ничего не улучшает:

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

У меня быстро заканчиваются идеи о том, как прогрессировать. Как я могу исследовать дальше и/или что может быть основной причиной медленной презентации?

Edit

Некоторые запутанные открытия:

  • Я удалил весь код из представленного контроллера представления. Производительность не изменяется.
  • У меня есть другой контроллер, который я представляю с одного и того же места с помощью другой кнопки. Он одинаково медленный.
  • в представлении контроллера имеется довольно много подзадач и ограничений - даже некоторые дочерние контроллеры. Удаление кода, который заполняет эти проблемы, устраняет проблему.
  • в 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]];

Я все еще очень смущен относительно того, почему эти ограничения приводят к тому, что презентация другого модального висит, и почему одна вариация ограничения ведет себя по-разному друг к другу.

Ответы

Ответ 1

Не уверен, что это была проблема с оригинальным автором, но вот что-то, что разрешило мне подобную проблему: я пытался представить представление из didSelectRowAtIndexPath, и мне пришлось называть deselectRowAtIndexPath раньше. Если это может помочь кому-то...

Ответ 2

Ваше приложение не отвечает из-за нескольких операций добавления и удаления в наборе. Если вы делаете какую-либо тяжелую обработку в основной теме, приложение получает блок и становится невосприимчивым.

Short 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 в фоновом потоке. Вы не должны делать какие-либо элементы пользовательского интерфейса в фоновом потоке.

Ответ 3

Я знаю, что я отправляю ответ на год позже. Но если это полезно для кого-то еще.

Попробуйте положить (быстрый код)

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

для отображаемого контроллера представления (и если он не работает, попробуйте поместить его в родительский элемент. Я поставил его на обоих, он просто помогает сгладить все другие анимации)

Надеюсь, что это поможет.

Ответ 4

Добавление строки:

CFRunLoopWakeUp(CFRunLoopGetCurrent());

После:

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

Исправлена ​​ошибка.

Ответ сделан из этой темы. Найдено благодаря комментарию Eugene H.