На Лекции 9 курса Стэнфорда CS193p — «Developing Application for iOS» («Разработка приложений для iOS») Пол Хэгерти рассматривает супер важную тему — Property Wrappers (“Обертки Свойства”). Мы наконец-то поймем, что такие вещи, как @State и @Published, делают “под капотом”. Далее профессор слегка затрагивает тему “издателей” Publishers, потому что если мы начинаем говорить о @Published, то быстро приходим к этой очень важной теме, однако на этой Лекции 9 дается лишь некоторый обзор на эту тему, более подробно эта тема будет обсуждаться позже.
Затем мы погружаемся в демонстрационный пример, в котором профессор показывает нам где, когда и как используются “издатели” Publishers, а также говорит о @Binding, который является новой для нас Property Wrapper (“Оберткой Свойства”). Сочетание этих двух механизмов позволяет нам ссылаться на «единственный источник истины» (source of truth) для данных, а не требовать их копирования, что может быть подвержено ошибкам.
Property Wrappers (“Обертки Свойства”) представляются в виде >@Something, и вы уже видели их как @State и @Published. Оказывается, на самом деле это просто структура struct, а в этой структуре есть код, который применяет некоторый шаблон “поведения” ко всем переменным vars, которые эти структуры struct “оборачивают”. Вы уже знаете о некоторых таких “поведениях”.
Например, @State заставляет переменную var “жить” в “куче” (heap), делая её writable в View, то есть дает возможность “писать” в нее новые значения в противоположность обычным переменным var в View, которые являются unwritable.
Мы знаем, что @Published публикует изменения переменной var, заставляя Views перерисовывать себя или делать другие подобные вещи.
То же самое происходит с @ObservedObject, которая отслеживает изменения в вашей ViewModel и заставляет View перерисовывать себя.
Property Wrapper (“Обертка Свойства”) — это конструкция языка Swift, которая добавляет “синтаксического сахара”, чтобы сделать эти структуры struct легко используемыми в вашем коде.
Внутри этой структуры struct есть очень важная переменная var, которая называется wrappedValue . ТИП этой переменной var wrappedValue для большинства Property Wrappers (“Оберток Свойства”) совпадает с ТИПом переменной var, которую они оборачивают. Есть еще одна переменная var в этой структуре struct, которая называется projectedValue. Доступ к этой переменной projectedValue осуществляется с помощью ещё одного “синтаксического сахара” — знака $, например, $emojiArt. У каждого Property Wrapper (“Обертки Свойства”) имеется свой отличающийся от других ТИП projectedValue, это полностью его решение. Например, @Published выбрала для себя в качестве projectedValue “издателя” Publisher, который публикует wrappedValue и никогда Never не ошибается.
Главный смысл Property Wrapper заключается в том, что структура struct Property Wrapper (“Обертки Свойства”) типа Published, может что-то ещё делать при получении (get) или установки (set) wrappedValue.
Например, что делает Published, когда его wrappedValue установлен? Он публикует это значение через свою переменную $emojiArt, которая является “издателем” Publisher. Но не только это, Published посылает сообщение objectWillChange.send() в ObservableObject, в котором он находится. Таким образом, Published оказывается вовлеченным в установку (setting) и получение (getting) этой переменной var, а это именно то, что на самом деле делают Property Wrappers (“Обертки Свойства”).
Затем профессор подробно рассматривает предпринимаемые действия и projectedValue каждого из известных нам Property Wrappers (“Оберток Свойства”): @State, @Published, @ObservedObject, @Binding, @EnvironmentObject, @Environment.
“Издатель” Publisher публикует определенный ТИП данных Output и может ошибаться с определенным ТИПом ошибок Failure, что мы можем с ним делать?
Самая главное, что мы можем делать с “издателями” Publishers, это «слушать» их. «Слушать» их — значит “подписаться” (subscribe) на них. Мы рассмотрим два наиболее распространенных способах сделать это: sink и assign
Далее профессор существенно модернизирует демонстрационное приложение EmojiArt в плане:
- предоставления пользователю обратной связи при загрузке фонового изображения из интернета,
- использование @Published “издателя” для автосохранения,
- использование .onReceive для автоматического масштабирования с целью “подгонки” при изменении фонового изображения,
- применение URLSession “издатель” для загрузки изображения,
- добавляем Выбор Палитры (@Binding)
Код демонстрационного примера для Лекции 9 находится на сайте курса CS193P и на Github для iOS 13 в папке Memorize L9.
Русскоязычный неавторизованный конспект Лекции 9, хронометрированный через каждые 5 минут, и представленный в виде PDF-файла, который можно скачать и использовать offline, а также в формате Google Doc доступны на платной основе.