Как я могу запретить Cocoa вызывать drawRect на каждом полностью невидимом подвью - PullRequest
0 голосов
/ 12 мая 2018

У меня есть полностью работающее, очень быстрое приложение с одним окном, написанное на Objective-C и изначально разработанное для MacOS 10.7 с использованием XCode 4. Оно имеет один вид прокрутки, показывающий части одного большого представления контента с множеством подвидов.Отображается только часть каждого вложенного представления, и только тот изначально отображаемый подсвеч получает свой метод -drawRect, вызываемый, когда приложение показывает начальное окно.Прокручиваемое представление содержимого, а также все его под-представления и под-подвиги создаются программно при запуске приложения (не из файла xib).

Каждый под-вид обычно имеет различные элементы управления иодно специальное подклассифицированное подвидовое представление, которое отображает ресурсоемкий чертеж, который предварительно вычисляется и кэшируется при первом вызове его метода -drawRect.Так что прокрутка всего этого распределяет вычисления и кэширование до того момента, когда пользователь должен это увидеть.Все это хорошо работает и делает это годами.Ни один из методов -drawRect под-представлений никогда не вызывается до тех пор, пока у под-представления не появится часть, которая станет видимой в иерархии во время прокрутки.

Проблема заключается в том, чтотеперь портировал приложение на XCode 9.3 и MacOS 10.13.4 и обнаружил, что после первого показа одиночного окна с прокруткой в ​​нем при запуске на рабочем столе каждое подподображение имеет -drawRect метод, вызываемый средой выполнения Какао, даже если none подподображений даже пространственно близки к тому, чтобы быть видимыми в иерархии представлений внутри прокручиваемого представления в окне.Это приводит к предварительному вычислению и кешированию каждого из вложенных представлений до того, как пользователь сможет взаимодействовать с только что запущенным приложением.Это занимает много секунд, что недопустимо в пользовательском интерфейсе.

Я понятия не имею, что мог бы сделать мой неизмененный код, чтобы заставить все невидимые подподображения проситься нарисовать себя, и поэтомукажется, что это новое положение вещей может быть связано с некоторыми более поздними изменениями в поведении Apple.Я попытался запросить свойство -isHiddenOrHasHiddenAncestor подподображения внутри -drawRect, но оно всегда возвращает false, возможно, потому что суперпредставления логически видимы, но обрезаются прокруткой.

Как можно отладить эту ситуацию, которая кажется совершенно противоположной тому, что система представления должна делать автоматически?При каких обстоятельствах система вызывает представление -drawRect, когда фрейм представления совершенно не может ничего показать?Что-то изменилось на стороне Apple?

1 Ответ

0 голосов
/ 13 мая 2018

Это может быть связано с «отзывчивой прокруткой», которая была введена в 10.9 и включена только для приложений, связанных с 10.8 SDK или новее. Лучшая консолидированная документация, вероятно, содержится в примечаниях к выпуску 10.9 AppKit . Обязательно ознакомьтесь с разделом «Перерисовать» немного ниже по документу, который (если я прав) является конкретной причиной того, что ваши невидимые виды просят рисовать.

Быстрый, но грязный способ предотвратить это - переопределить класс одного из задействованных представлений +isCompatibleWithResponsiveScrolling для возврата false.

Но, может быть, лучше выполнить вычисления асинхронно в фоновом потоке. Ваше представление будет рисовать некоторые дешевые заполнителя (или ничего), пока вычисления не будут завершены. По завершении вы бы отметили это как нужное отображение. (Обязательно перенесите всю работу пользовательского интерфейса из фонового потока обратно в основной поток.) ​​

Вы также можете отложить создание ваших подпредставлений (или подподвидов) и использовать переопределение -prepareContentInRect: для их создания по мере необходимости. Или используйте переопределение этого метода, чтобы отключить переопределение, как описано в примечаниях к выпуску.

...