All streams
Search
Write a publication
Pull to refresh

Comments 9

Поясните пожалуйста, как didReceiveMemoryWarning официально устарел, если в документации сказано, что настоятельно рекомендуется его реализовать

Спасибо за замечание,
didReceiveMemoryWarning() действительно до сих пор присутствует в API и формально не помечен как deprecated. Однако начиная с iOS 11–13 система стала по-другому управлять памятью: при нехватке ресурсов iOS чаще выгружает представления неактивных контроллеров или завершает приложение целиком, вместо того чтобы массово рассылать memory warning. Поэтому в современных проектах метод почти не используется, и большинство разработчиков оставляют его пустым или вовсе игнорируют.
Формулировка «Your app should implement this method to release any additional memory…» действительно есть в документации. Она появилась ещё во времена iOS 6–8, когда приложения часто падали от нехватки памяти, и каждый контроллер обязан был чистить тяжёлые ресурсы (картинки, кэши, массивы данных). Apple не убрала эту рекомендацию из текста, потому что она актуальна для обратной совместимости и для приложений, поддерживающих старые версии iOS или работающих с действительно массивными кэшами.
Вы правы, я некорректно выразился в статье, и формулировки лучше поправить, чтобы не вводить читателей в заблуждение. Корректнее будет сказать, что метод не устарел официально.

Даже не совсем так. WWDC сессия по управлению памятью рекомендует НЕ освобождать данные в массивах и тд потому что система использует сжатие памяти и если начать трогать объекты в массивах(и тд) даже для того что бы удалить это может привести к увеличению потребления памяти так как системе придется разжать эту область памяти. Поэтому рекомендуется на время например перестать что то кэшировать и тд и обнулить ссылки на объекты которые больше не нужны и могут быть легко восстановлены (Это относится и к структурам данных, обнулить их можно. Итерироваться что б найти например не нужные данные не стоит).

Спасибо за дополнение! Да, вы правы – начиная с iOS 11 Apple внедрила memory compression, и из-за этого агрессивное «чистить массивы» в didReceiveMemoryWarning() может привести к обратному эффекту. Я немного упростил в статье, но стоит добавить этот нюанс для полноты картины.

  • рекомендуется вызывать setNeedsUpdateConstraints(), если состояние изменилось, и не трогать сами constraints в viewDidLayoutSubviews.

в каких конкретно случаях вам нужно вызвать вручную метод setNeedsUpdateConstraints ? Constraints - это же не frame/bounds, значение которых может меняться со временем без вашего участия.

Привет, спасибо за вопрос. Вот конкретные случаи, когда имеет смысл вызвать setNeedsUpdateConstraints() вручную:

  1. Динамическое изменение UI-состояния. Например, у кнопки появилось/исчезло дополнительное изображение, и теперь ширина/высота должны учитываться по-другому.

  2. Смена layout mode внутри кастомной вью. Например, кастомный компонент (таблица/чипы) может переключаться между «горизонтальным» и «вертикальным» режимом. При переключении нужно обновить набор констрейнтов.

  3. Зависимость констрейнтов от данных. Например, в карточке у тебя есть UILabel, и если текст длинный — включается ограничение по ширине, а если короткий — центрирование. Такие переключения удобнее делать через updateConstraints.

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

1 и 4 - может быть, не пробовал.

2 и 3 - а чем это отличается от варианта держать 2 набора constraints и активировать/деактивировать их?

"Пакетно" менять констрэинты (например, переключаться между 2 наборами) рекомендуется делать в updateConstraints, а setNeedsUpdateConstraints как раз и подсказывает системе, что надо произвести очередной layout pass (во время которого будет вызван updateConstraints) побыстрее, а не тогда, когда системе будет удобно.

Неудачный пример с loadViewIfNeeded

child.loadViewIfNeeded()
view.addSubview(child.view)

Если закомментировать первую строку, результат не изменится: если view == nil, то первое обращение к этому свойству приедет к загрузке view, т.е. будет вызов loadView и т.д.

Этот метод - скорее как альтернатива некрасивому

_ = child.view
Sign up to leave a comment.

Articles