Это Лекция 16 курса Stanford CS193p, весна 2021 года.
Эта лекция полностью посвящена мультиплатформенной поддержке. В частности, запускается приложение EmojiArt на Mac как собственное приложение для macOS, но при этом вы будете удивлены парой вещей. Одна из них — это какой мощный UI мы создали для работы с документами на Mac на базе документо-ориентированной SwiftUI архитектуры, а также сколько нашего iOS кода практически без модификации работает на Mac. Для той части, которая не работает, применяется несколько стратегических хитростей, способных максимально адаптировать наш код к мультиплатформенности.
На Лекции 16 профессор создает единый проект с большим количеством общего кода, и да, с некоторыми #if os(…) — else #endif, потому что две платформы, macOS и iOS, это не одно и то же. У них не совсем один и тот же способ взаимодействия с пользователями и т. д., так что он адаптирует код к разным платформам.
Хотя в конце Лекции 16 мы получаем полностью Mac версию приложения EmojiArt. В действительности целью этой Лекции 16 является понимание некоторых стратегий использования общей кодовой базы между двумя системами, macOS и iOS, и получение максимально работающего кода.
Все начинается с создание нового мультиплатформенного Multiplatform документо-ориентированного Document App приложения на основании шаблон, который для начала предоставляется Xcode, который содержит общую папку Shared и отдельные папки iOS и macOS для двух различных платформ, которые содержат различные файлы Info.plist. В общую часть Shared копируется код, полученный для iOS версии на предыдущих Лекциях, а в каждый из отдельных Info.plist настройки Info.plist из iOS версии, которые связаны с документной ориентацией приложения EmojiArt.
Затем проект для macOS компилируется(⌘B), и мы видим множество ошибок компиляции, которые профессор рассматривает одну за другой и предлагает то или иное решение.
В результате часть файлов Camera и PhotoLibrary, относящихся к фотокамере и Библиотеки Фотографий, которых нет на Mac, прямиком переехала в iOS раздел, а ссылки на них в общем коде пришлось имитировать с помощью EmptyView ( ) в специальном файле macOS.swift. Теперь Camera определена и на Mac, но это просто структура struct Camera, чья переменная isAvailable всегда равна false, так что она никогда ничего не делает.
Для horizontalSizeClass, которого тоже нет на Mac, нам пришлось использовать конструкцию #if os (iOS) — #endif для компилятора.
Получение данных изображения Data выполняется по-разному на двух платформах: с помощью jpegData — в iOS, tiffRepresentation — в macOS. В этом случае мы создаем некоторую абстракцию imageData, которая реализуется как расширение extension класса UIImage по-разному и в разных файлах для разных платформ:
У нас появляется довольно интересная стратегия компромисса, либо вы пытаетесь собирать все вещи в специальном файле для конкретной платформы, либо вы выполняете #if os(macOS) — #endif или #if os(iOS) — #endif, которые рассеяны по всему вашему коду.
После запуска приложения на Mac, нам пришлось еще немного поработать над совместным кодом, потому что технология Drag & Drop на Mac работает немного с другими объектами, чем на iOS, потому что стиль кнопок Button отличается от стиля кнопок на iOS, потому что вид «всплывающего окна» Popover также отличается на iOS и macOS, потому что доступ к файлам из интернета на Mac регулируется специальными правами entitlements. Но все изменения укладываются в нашу компромиссную стратегию использования отдельных файлов для каждой конкретной платформы и конструкции #if os(macOS) — #endif или #if os(iOS) — #endif компилятора, а также в добавление дополнительных строк в entitlements.
В результате, приложение на Mac работает замечательно. В Mac приложении круто то, что мы можем изменить размер наших документов. Мы можем также сохранять документы с помощью Command-S.
Есть ещё одна замечательная вещь на Mac — это то, что мы не только получаем множество “окон” Windows одновременно. Но мы также можем собрать их все во вкладках Tab. Если вы в меню перейдете на Show Tab Bar (показать панель вкладок), то получите вкладки Tab прямо здесь и сможете прямо здесь добавлять новые вкладки Tab. Вы также можете выбрать Show All Tab (показать все вкладки). Это позволит выбрать нужное вам изображение на вкладках.
Итак, это действительно довольно мощный UI для документо-ориентированного приложения, которое вы получаете бесплатно с помощью SwiftUI. Просто удивительно, сколько нашего iOS кода способно работать на Mac.
Код демонстрационного примера для Лекции 16 находится на Github для iOS 14 в папке EmojiArtL 16.
Русскоязычный неавторизованный конспект Лекции 16, иллюстрированный, хронометрированный и представленный в виде PDF-файла, который можно скачать и использовать offline, а также в формате Google Doc доступны на платной основе.