Проблема с производительностью автомакета iOS в портретном режиме. [Оптимизация NSISEngine]

Я столкнулся с очень странной проблемой, и мне было интересно, может ли кто-нибудь помочь мне здесь, так как я полностью потерян.

Контекст: я разрабатываю приложение с относительно простой иерархией. Всего несколько контроллеров просмотра, но довольно много изображений в высоком разрешении. Они представлены в виде UIScrollView с некоторым текстом и т. д. При тестировании в портретном режиме прокрутка не прокручивалась плавно. Казалось, что частота кадров упала примерно до 4-5 кадров в секунду. Сначала я подумал, что это из-за изображений в высоком разрешении.

Но затем я перевел iPad в ландшафтный режим, и все пошло гладко. Поскольку у меня есть отдельный xib-файл для портретной и альбомной ориентации, я подумал, что проблема должна быть в портретном xib. Оказалось, не было. У обоих был один и тот же VC-класс, и поэтому они использовали один и тот же код, и оба xib почти идентичны, за исключением размеров и позиций представлений.

Чтобы сузить проблему, я использовал инструмент TimeProfiler, чтобы увидеть, что вызывает проблему. Как оказалось, TimeProfiler показал некоторые вызовы [NSISEngine optimize] (инициированные NSLayoutConstraint). В портретном режиме было больше звонков и эти звонки длились намного дольше. Дальше по дереву я увидел, что в портретном режиме [NSISEngine optimize] вызывает [NSISEngine fixupIntegralizationViolations], а в альбомном нет.

Я даже удалил все контроллеры просмотра из приложения, кроме rootVC и еще одного, который представлен rootVC. Представленный vc содержит только изображения, кнопки и анимацию. Он имеет только один xib для обеих ориентаций и (как и все остальные) выложен с автомакетом.

Макет работает как надо в обеих ориентациях, и нет никаких неясностей (насколько я могу судить, по крайней мере po [[UIWindow keyWindow] _autolayoutTrace] ничего не показывает).

Я приложил скриншот TimeProfile процесса презентации vc. Один для портрета и один для пейзажа. Как видите, в альбомной ориентации вызовы [NSISEngine optimize] занимают всего миллисекунду, а в портретной — более 3000 мс.

Есть ли кто-нибудь, кто может сказать мне, почему это так? Или, может быть, есть идеи, что я могу сделать, чтобы выяснить, в чем проблема?

Любая помощь будет принята с благодарностью!

Спасибо

Ссылка на увеличенную версию изображения: ссылка

Снимок экрана инструментов Timeprofiler


person Tobi    schedule 18.10.2012    source источник


Ответы (3)


Я столкнулся с той же проблемой с умеренно сложным видом, где он хорошо работал на iPad без Retina или на iPad с Retina в портретном режиме. В ландшафтном режиме на устройстве Retina требовалось в 10 раз больше времени, чтобы отобразить всплывающее окно или добавить другое представление в стек представлений. В итоге я заменил файл XIB на закодированный вручную loadView в контроллере представления. Кажется, это устранило проблему. Конструктор интерфейса имеет тенденцию создавать чрезмерные ограничения, поэтому контроль над этим является ключом к хорошей производительности автоматической компоновки.

Я также открыл билет поддержки по этой проблеме.

Обновлять:

Я нашел причину в моей ситуации. Это был следующий набор ограничений:

NSArray *constraints = [NSLayoutConstraint
                        constraintsWithVisualFormat : @"|[sunLabel][monLabel(==sunLabel)][tueLabel(==sunLabel)][wedLabel(==sunLabel)][thuLabel(==sunLabel)][friLabel(==sunLabel)][satLabel(==sunLabel)]|"
                        options : 0
                        metrics : nil
                        views : labelViewsDictionary];

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

Чтобы решить эту проблему, я создал массив ограничений, определяющих ширину каждой метки, и применил эти ограничения. Когда устройство поворачивается, ширина родителя изменяется, поэтому я возвращаюсь и настраиваю константу в ограничениях на 1/7 ширины родительского представления. Теперь это работает хорошо, процесс загрузки всплывающего окна теперь занимает менее 300 мс, а не 2000 мс.

person Jack Cox    schedule 29.03.2013

Я написал запрос в техподдержку по этой проблеме и в итоге получил ответ, что скорее всего это баг. Отчет об ошибке отправлен. Надеюсь, скоро исправят. Если будут новости, я обновлю этот ответ.

person Tobi    schedule 26.10.2012
comment
просто любопытно, были ли у вас какие-либо последующие действия с этим отчетом об ошибке? У меня были похожие проблемы со странными задержками автомакета, когда инструменты показывали много вызовов NSISEngine fixUpIntegralizationViolations... - person Peter E; 25.02.2013
comment
Нет, к сожалению, я еще ничего не слышал - person Tobi; 07.03.2013

Вчера у меня была такая же проблема на устройстве Ipad iOS6.1. Инструментирование приложения показало, что метод fixupIntegralizationViolations занимал около 300 мс при каждом вызове (около 20 раз, что очень много), что делало приложение абсолютно бесполезным.

Моя проблема была очень похожа на ту, что комментирует Джек Кокс, но я решил ее по-другому. Мое ограничение было:

@"H:|[allButton][inStoreButton(==allButton)][onlineButton(==allButton)][sortButton(50)]|"

Проблема в том, что parentView здесь представляет собой полную ширину iPad в альбомной ориентации, поэтому математика этого ограничения давала каждой кнопке эту ширину: (1024-50)/3 = 324,6666667.

Обычно это не проблема в автомакете, поскольку он заботится о больших числах с плавающей запятой и правильно их округляет, но кажется, что в iPad iOS6 Ландшафтное округление этих чисел вызывает ошибку, которая блокирует пользовательский интерфейс. Чтобы обойти это, все, что мне нужно было сделать, это изменить sortButton на 52, поэтому ширина каждой кнопки теперь составляет: (1024-52)/3 = 324. Вот и все. Теперь метод fixupIntegralizationViolations занимает около 1 мс при каждом вызове.

Интересно то, что использование 52 дает не десятичную ширину в альбомной ориентации, но дает десятичное число в портретной ориентации: (768-52)/3 = 238,666667. Тем не менее, у портрета, похоже, нет ошибок, и авторазметка правильно округляет числа.

person Pauls    schedule 15.05.2014