Медленная производительность для 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.