Как определить различные конфигурации для нашего проекта
Нам часто приходится организовывать наши мобильные доставки. Это означает, что сборка, которую мы используем для публикации нашего приложения в App Store, или сборка, которую мы используем каждый день для локальной сборки нашего приложения или для внутреннего распространения в нашей компании, — это не одно и то же.
Здесь мы увидим способ немного лучше организовать доставку наших приложений и начнем организовывать их во внутренних конфигурациях, которые имеют смысл в нашей повседневной работе.
О схемах сборки
Из Документов Apple:
Когда вы создаете, запускаете, тестируете, профилируете или архивируете часть своего проекта, Xcode использует выбранную схему сборки, чтобы определить, что делать. Схема сборки содержит список целей для сборки, а также любые сведения о конфигурации и среде, влияющие на выбранное действие. Например, когда вы создаете и запускаете приложение, схема сообщает Xcode, какие аргументы запуска нужно передать приложению. Xcode предоставляет схемы по умолчанию для большинства целей, и вы можете настроить эти схемы или создать новые по мере необходимости.
Схема сборки — это в основном конфигурация, которая связывает цель и любую конфигурацию, которая может нам понадобиться для этой цели. Сюда входят переменные среды, файлы конфигурации и все, что может сделать сборку настраиваемой.
Например, у нас могут быть три следующие схемы:
- Схема производства, которую наши пользователи могут скачать в App Store
- Постановочная схема или схема внутреннего тестирования. Также может называться Бета
- Схема разработки, которая используется локально инженерами
Такое разделение проблем с точки зрения конфигурации сборки может помочь нам настроить взаимодействие с нашим приложением. С такими типами схем мы можем, например:
- Изменить значок приложения
- Используйте другой базовый URL для нашего внутреннего API
- Настройте сторонний SDK в соответствующих средах.
- Добавьте внутренние инструменты разработки, которые могут помочь командам QA или Devs.
- Избегайте отправки информации третьим лицам, например, нам не нужно будет отправлять информацию о сбоях в Firebase, если мы компилируем приложение локально. Это добавило бы ненастоящие данные на панель сбоев.
Схемы против целей
В структуре нашей системы сборки есть еще один важный компонент, и это цель. Цель — это в основном приложение, которое мы создаем, продукт, который мы стремимся создать. Это означает, что весь исходный код необходимо скомпилировать и, наконец, создать двоичный файл. Цель использует схему для создания продукта. Мы можем резюмировать различия следующим образом:
Цель определяет продукт для сборки и содержит инструкции по сборке продукта из набора файлов в проекте или рабочей области.
Схема Xcode определяет набор целей для сборки, конфигурацию, используемую при сборке, и набор тестов для выполнения.
Поскольку мы можем использовать цели для дифференциации конфигурации, это не является их целью. В итоге мы усложним систему сборки и опыт разработчиков, использующих проект. Цель создает продукт, а схема содержит конфигурацию того, как его создать.
Файлы конфигурации Xcode
Ключевым элементом использования схем является использование файлов конфигурации Xcode. Это те, у которых расширение .xcconfig
.
По сути, мы можем определить пользовательские значения для нашей желаемой конфигурации сборки, которые мы можем использовать позже для создания нашей цели. Пример:
Мы можем создать много файлов .xcconfig
и ссылаться в них друг на друга, чтобы избежать повторения общих значений между конфигурациями. В следующем разделе эта концепция будет объяснена лучше.
Пример проекта
Для нашего примерного проекта у нас будет следующее:
- 1 цель под названием
schemes-test
- 2 схемы под названием
STDevelopment
иSTProduction
- 3 файла
.xcconfig
:Common.xcconfig
,Development.xcconfig
иProduction.xcconfig
Поскольку цель уже создана, когда у нас есть новый проект, мы приступим к созданию схем. Мы коснемся опции «Управление схемами…» в верхнем меню рядом с названием проекта:
Затем в представлении списка схем мы нажмем кнопку +, чтобы создать новую схему.
Мы создадим новую схему с именем STDevelopment
:
То же самое для STProduction
На данный момент у нас должны быть следующие схемы в нашем списке:
Автоматически сгенерированную схему schemes-test
можно удалить, так как мы не будем ее использовать.
Теперь мы приступим к созданию файлов .xcconfig
. Нам нужно создать папку BuildConfigurations
в корне нашего проекта.
Затем мы создадим новый файл с типом Configuration Settings File
Мы назовем этот файл Common
. Затем мы делаем те же шаги для новых файлов Development
и Production
. На данный момент у нас должны быть эти файлы в нашем проекте:
В файле Common
введем следующий код
В Development
мы введем следующее:
И следующие строки для Production
:
Мы определяем следующие значения в наших файлах .xcconfig
:
PRODUCT_BUNDLE_IDENTIFIER
: Идентификатор пакета нашей схемы.MARKETING_VERSION
: номер версии сборки.CURRENT_PROJECT_VERSION
: номер сборкиBUNDLE_DISPLAY_NAME
: Видимое имя приложения на экране.
Как вы понимаете, с помощью ключевого слова #include
мы можем включать файлы. В нашем случае значения MARKETING_VERSION
и CURRENT_PROJECT_VERSION
должны оставаться одинаковыми между конфигурациями. Но значение для PRODUCT_BUNDLE_IDENTIFIER
отличается, так как мы хотим иметь разные приложения для обеих сред. То же самое для BUNDLE_DISPLAY_NAME
, которое является видимым именем приложения.
Теперь следующий шаг — связать эти файлы с конфигурациями. Для этого заходим в настройки проекта:
Здесь мы заменим имена Debug
и Release
на Development
и Production
, чтобы они соответствовали именам наших файлов. Также добавляем в каждую конфигурацию соответствующие файлы xcconfig:
Чтобы иметь возможность использовать эти значения, нам нужно перейти к нашему файлу Info.plist
, где мы добавим следующие свойства с каждой соответствующей переменной:
Bundle identifier
сPRODUCT_BUNDLE_IDENTIFIER
Bundle version string (short)
сMARKETING_VERSION
Bundle version
сCURRENT_PROJECT_VERSION
Bundle display name
сBUNDLE_DISPLAY_NAME
Итак, мы закончим примерно так:
То же самое можно сделать, если мы нажмем на наши целевые настройки и установим $(…)
для каждой переменной в соответствующем поле:
В качестве последнего шага нам нужно связать каждую схему с каждой конфигурацией, поэтому мы нажимаем «Редактировать схему» на верхней панели:
Мы свяжем каждую схему с соответствующей конфигурацией:
Вот и все! Если мы запустим наши схемы в симуляторе, то увидим, что у нас есть два разных приложения:
Проверка схем в коде
Мы можем включить код схемы в наш двоичный файл, если захотим. В этом конкретном случае мы можем использовать для Development.xcconfig
следующее:
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
И еще один для Production.xcconfig
:
SWIFT_ACTIVE_COMPILATION_CONDITIONS = RELEASE
Итак, в нашем коде может быть следующее:
Это очень полезно для представления скрытых меню или утилит разработчика/QA, помогающих в отладке.
Соответствие версии и номера сборки между приложением и расширениями
Важно сделать одинаковые изменения номеров для тестовой цели, чтобы и основная, и тестовая цель имели одинаковые номера версии и сборки. Тот же случай для расширений приложений. Нам нужно сохранить один и тот же номер версии и сборки между основной целью и расширениями приложений, иначе Apple предупредит нас, когда мы загрузим сборку в App Store Connect. Сообщение будет похоже на следующее (также будет получено по электронной почте)
О добавлении токенов или ключей API
Мы можем добавить ключи/токены API в файлы .xcconfig
, чтобы затем мы могли определить их в файлах plist
и получить к ним доступ следующим образом:
let bundleId = Bundle.main.infoDictionary?["APIKey"] as? String
Однако это не безопасное решение. Мы должны попытаться получить такие конфиденциальные данные другим способом, потому что их фиксация в нашем репозитории git небезопасна. Если мы используем CI для создания и распространения нашего приложения, многие поставщики CI имеют возможность установить секреты (например, Bitrise), а затем внедрить эти секреты в проект с помощью решения, такого как cocoapods-keys. О том, как это сделать, я расскажу в следующем посте.
Заключение
Мы увидели, как определить различные конфигурации для нашего проекта. Очень полезно быть организованным таким образом, чтобы мы могли использовать одну сборку для локальной разработки, а другую — для производства. Эта возможность позволит нам добавлять надлежащие инструменты тестирования, лучше определять сторонние среды или просто организовывать наш код более эффективным способом.
Полный исходник можно посмотреть здесь.
Спасибо за прочтение!