Лекция 10 CS193P Fall 2017 — Многопоточность и Autolayout.

Судя по названию, основными темами Лекции 10 являются:

  1. Многопоточность,
  2. Система Autolayout,

но очень значительная часть Лекции 10 посвящена также усовершенствованию функциональных возможностей демонстрационного приложения Cassini по следующим направлениям :

  • использование множественного MVC Split View Controller в сочетании с парой Navigation Controllers для обеспечения функционирования на iPhone и iPad
  • применение extension для расширения возможностей класса UIViewController в плане получения содержимого content в случае использования или неиспользования Navigation Controller
  • тонкости использования индикатора активности  (Activity Indicator) в виде маленького вращающегося «колесика» для визуализации занятости системы

В результате получился универсальный, подходящий на все случаи жизни, как в дальнейшем покажет практика, MVC для показа изображений по их URL —  ImageViewController. Огромный объем изображений NASA, задействованных в демонстрационном приложении Cassini , наглядно показывает необходимость использования многопоточности.

Многопоточность

Это одна из фундаментальных тем для программирования на мобильных устройствах. Но на Лекции 10 рассматривается лишь та часть многопоточности, которая решает проблему поддержания UI в «отзывчивом» и активном состоянии, выталкивая все, что может быть медленным или блокирующим вследствие ожидания ресурсов, в другой поток, отличный от main queue (главной очереди).  Последовательная очередь main queueDispatchQueue.main, предназначена для взаимодействия с пользователем и должна всегда оставаться свободной. Кроме того, она защищает UI от “разлаживания” в многопоточной среде, поэтому все действия с элементам UI должны выполняться в main queue последовательно в строгом порядке.

В качестве других очередей, куда можно «сбрасывать» ресурсо-емкие операции, в Лекции 10 рассматриваются глобальные параллельные (concurrent) очереди DispatchQueue.global (qos:  QoS) . Показано, как просто выполнять переключения между этими очередями с помощью Grand Central Dispatc в Swift. По существу, профессору понадобился маленький (5 строк) совершенно замечательный кусочек кода, в котором уместилось очень много всяких тем: список захвата [weak self], проверка возвращающихся и уже устаревших и ненужных изображений url ==  self?.imageURL, обратное переключение на main queue, получение одной из глобальных фоновых (background) очередей с QoS.

Но при всей простоте кода, методы многопоточного программирования требуют более изощренного воображения и более широкого взгляда на действия, происходящие в приложении. Дело в том, что в многопоточном программировании отдельные куски кода (чаще замыкания) в разных потоках выполняются не в том порядке, как это написано в коде. Как с этим справиться показано на примере приложения Cassini.

Autolayout

Вторя часть Лекции 10 посвящена очень важной теме: механизму Autolayout (автоматическое расположение). Это блестящий мастер-класс по использованию Autolayout и концепции Size Classes, в котором профессор детально рассказывает абсолютно все о каждой опции.
Сначала дается обзор того, что нам уже известно об Autolayout  к этому моменту времени, так как во всех предыдущих лекциях элементы Autolayout уже были представлены в той или иной степени. Это направляющие голубые пунктирные линии, это использование CTRL-перетягивания, как способа # 1 для создания ограничений системы Autolayout, а также меню «Pin» и «Align«. Очень важная роль в системе Autolayout  отводится такой концепции, как Size Class. Теперь в iOS без нее уже не обойтись. 
Общую большую картину всех ваших ограничений вы можете получить в Document Outline (схеме UI), который является своеобразной «штаб-квартирой» системы Autolayout,  Именно здесь можно определить, какие ограничения действуют в определенном Size Class, можно разрешить конфликты между ограничениями, можно вести «охоту» за «магическими» числами.

При вращении вашего пользовательского интерфейса (UI) его геометрия меняется столь кардинально, что механизма Autolayout уже не хватает, чтобы перепозиционировать все элемены UI. Прекрасным примером этого является наша игра Концентрация с 4 кнопками по горизонтали и 5 кнопками по вертикали. Это очень хорошо смотрится в портретном режиме, когда все кнопки близки к квадратным. Но в ландшафтном режиме кнопки сильно деформируются — они  становятся более широкими и плоскими. Было бы лучше, если бы в ландшафтном режиме у нас было 5 кнопок по горизонтали и 4 кнопки по вертикали и осталось бы дополнительное место для размещения метки с числом переворотов карт. Но у механизма Autolayout нет способа сделать это простой установкой ограничений.

Решение этой проблемы называется “Size Class”. Все View Controllers , в том числе и ваш Concentration View Controller, всегда существуют в среде Size Class с определенной шириной (width) и высотой ( height). В настоящий момент Size Class может иметь ТОЛЬКО ДВА значения:  либо Compact, либо Regular

Пол Хэгерти показывает демонстрационный пример, в котором заставляет UI игры Концентрация реагировать на среду Size Class, в которой он находится. При этом он избирает разные по сложности стратегии:

  • простейшуя настройку свойств элементов UI на различные Size Classes, позволяющие скрывать различные части UI,
  • проектирование различных ограничений (constraints) UI элементов для различных Size Classes с помощью «волшебной» кнопки “Vary for Traits”, 
  • использование traitCollection и соответствующих методов «жизненного цикла» View Controller типа traitCollectionDidChange в коде.

Когда работа с  Size Classes, наконец, закончена, то есть все ограничения (constraints) созданы правильно, то  работа этой концепции на разных устройствах, в портретном и ландшафтном режимах, при локализации на различных языках кажется «магией».

 Код демонстрационных примеров для Лекции 10 находится на Github  для iOS 11  и на Github для iOS 12 в папках Cassini L10 и Concentration L10. Лекция 10 и слайды на английском языке находятся на  iTunes название “10. Multithreading and Autolayout.”

Русскоязычный неавторизованный конспект Лекции 10, хронометрированный через каждые 5 минут, и представленный в виде PDF-файла, который можно скачать и использовать offline, а также в формате Google Doc доступны на платной основе.