Лучшие практики и инструменты при разработке iOS приложений
Разрабатывая мобильные приложения, мне не раз приходилось создавать проекты с нуля. При этом я и моя команда всегда тратили много времени на основную настройку проекта, такие как интеграция сторонних инструментов, настройка структуры проекта, написание базовых классов, интеграция внешних библиотек и т.д.
Я решил, что время, затрачиваемое на запуск проекта, можно уменьшить, а основную часть процесса можно автоматизировать. При этом я собрал лучшие практики и инструменты, которые мы использовали, и подготовил шаблон проекта, который мы используем при запуске новых проектов. Такой шаблон должен сэкономить время разработчика на конфигурацию нового проекта, а также обеспечить общую структуру проекта, к которой привыкнет каждый член команды, чтобы больше не приходилось думать и изучать структуру нового для него проекта. Теперь это всегда одинаково.
Каждый инструмент или подход, добавленный в шаблон, заслуживают отдельной статьи, но я хотел бы попытаться суммировать каждый пункт и дать краткое объяснение того, почему я включил их в данную статью.
Cocoapods
Я не думаю, что Cocoapods требует представления. Это библиотека для управления внешними зависимостями для IOS проектов. Она существует уже давно и является надежной и проверенной на практике в тысячах (если не в миллионах) проектов. Также существуют и альтернативные менеджеры зависимостей, например: Carthage, но я решил продолжить с Cocoapods, потому что у нее самый широкий спектр поддерживаемых проектов с открытым исходным кодом. Использовать Cocoapods очень просто, и он предоставляется с search index, который позволяет легко находить пакеты, которые могут пригодиться в любой момент.
Проект шаблона предоставлен с простым Podfile, который содержит Swiftlint и R.swift. Шаблон также включает Gemfile для управления версией Cocoapods, используемой для управления зависимостями. Данное решение является часто игнорируемым разработчиками, но оно предотвращает проблемы, возникающие, когда разработчики Вашей команды устанавливают зависимости, используя различные версии Cocoapods. Gemfile принудительно использует одну и ту же версию Cocoapods для всей команды.
Swiftlint
Swiftlint — это очень полезный инструмент для обеспечения соблюдения определенных правил и стиля написания кода каждым разработчиком в одной команде. Данную систему можно было бы рассматривать, как автоматизированную систему проверки кода, которая предупреждает разработчика об опасных моментах, таких, как, например, force casts, force tries и т. д., но кроме вышесказанного, данная система применяет общий стиль написания кода, следя за тем, чтобы все разработчики следовали одинаковым правилам, связанным со «стилем кода», например: отступы или интервалы. Такой подход имеет огромные преимущества, не только выполняя экономию времени на проверку кода, но также делает файлы проекта узнаваемыми, что повышает их читабельность и, как следствие, их понимание всеми участниками команды разработчиков. По данной ссылке предоставлен список всех правил. В шаблоне, Swiftlint он устанавливается посредством Cocoapods и включается в шаг «Фазы компиляции», поэтому он покажет предупреждение разработчику при каждой компиляции проекта.
R.swift
R.swift — это инструмент для получения строго типизированных, автоматически заполненных ресурсов, таких как изображения, сегменты шрифты и локализации. Он выполняет все перечисленные действия путем сканирования проекта и создания классов, необходимых для получения ресурсов. Самым большим преимуществом этой библиотеки является то, что при использовании ресурсов она делает программный код:
Если вы ошиблись в названии изображения, вы получите ноль. Если какой-либо член вашей команды изменит имя ресурса изображения, этот код вернет ноль или его выполнение будет остановлено, если вы принудительно развернете изображение. При использовании R.swift это выглядит так:
Теперь вы можете быть уверены, что пиктограмма действительно существует (компилятор предупредит вас, если это не так, благодаря проверкам времени компиляции), и Вы будете явно уверены, что не сделаете опечатку в названии пиктограммы, поскольку будете использовать автозаполнение.
R.swift устанавливается посредством Cocoapods и интегрируется в шаблон в Фазе компиляции и будет генерировать классы оболочки Swift для каждой компиляции. Это означает, что если вы добавите файл / изображение / локализацию / шрифт / цвет / перо и т. д., то все это будет доступно посредством R.swift после компиляции проекта.
Отдельный файл AppDelegate для тестов
Очень часто забывают о хорошей практике использования отдельного класса TestAppDelegate при запуске тестов. Почему это хорошая идея? Обычно класс AppDelegate выполняет много работы при запуске приложения. Он может иметь логику конфигураций window, конфигурировать базовое отображение пользовательского интерфейса приложения, выполнить логику регистрации для получения уведомлений, иметь код настройки подключения к базе данных и даже иногда выполнять вызовы серверного API. Юнит тесты не должны иметь сайд эффектов. Вы действительно не хотите выполнять вызовы случайных API и настраивать всю структуру пользовательского интерфейса вашего приложения только для запуска юнит тестов?
TestAppDelegate также является подходящим выбором для того, чтобы получить код, который вы хотите запускать только один раз во время выполнения набора тестов. Он может содержать код, который генерирует мок-объекты, заглушки сетевых запросов и т. д.
Шаблон содержит файл main.swift, который является основной точкой входа для приложения. В этом файле есть методы, которые проверяют среду работы приложения, и, если это тестовая среда, они вызывают TestAppDelegate.
Флаги профилирования производительности компилятора
Swift — это отличный язык, более простой в использовании и более безопасный, чем Objective-C (IMO). Но когда он был впервые представлен, у него был один большой недостаток — время компиляции. Вернувшись в дни, когда я работал над проектом в Swift, в котором было примерно 40 тыс. строк кода Swift (проект среднего размера). Код был очень тяжелым, с параметрами настройки и выводом типов, а компиляция чистой сборки заняла почти 5 минут. При внесении даже небольших изменений, проект повторно компилируется и это занимает около 2 минут, чтобы увидеть изменения. Это было одним из худших событий, которые я когда-либо испытывал, и из-за этого я почти прекратил использовать Swift.
Тогда единственным решением было попытаться профилировать время компиляции проекта и изменить свой код таким образом, чтобы компилятор работал быстрее. В помощь решения таких проблем, Apple вводит некоторые неофициальные флаги компилятора, которые предупреждают разработчика, о том, что компиляция тела метода или определение типа выражения занимает слишком много времени. Я добавил эти флаги в проект шаблона, для предупреждения о длительном времени компиляции вашего приложения.
В наши дни, время компиляции значительно уменьшилось, и разработчикам очень редко приходится оптимизировать свой код только для того, чтобы уменьшить время компиляции. Но все же лучше обо всем знать заранее, чем пытаться решить данную проблему, когда проект становится слишком большим.
Dev/Staging/Production configurations
Еще один хороший подход (или, можно сказать, необходимость) — иметь отдельную конфигурацию и переменные среды для сред разработки, финального тестирования и публикаций приложения. В настоящее время почти каждое приложение должно работать с сервером, и обычно такие сервера развертываются в нескольких средах. Среда разработки используется для ежедневного развертывания разработчиками для тестирования своего кода. Среда финального тестирования используется для создания стабильных релизов или для тестирования тестировщиками и клиентами.
Одним из способов поддержки нескольких сред в проекте iOS является добавление конфигураций на уровне проекта.
Конфигурации уровня проекта
Определив конфигурации, можно создать файл Configuration.plist, содержащий переменные для каждой среды.
Configuration.plist
При запуске проекта имеется возможность указывать, какую конфигурацию следует использовать. Вы можете сделать это в схеме сборки.
Затем необходимо добавить еще одно свойство в файл проекта Info.plist. Значение данного свойства будет динамически подставляться во время выполнения в имя текущей конфигурации.
Все это предварительно настроено в шаблоне.
Осталось только написать класс, который может извлекать эти переменные во время выполнения в зависимости от конфигурации, выбранной в схеме сборки. Шаблон содержит класс ConfigurationManager, который может извлекать переменные для текущей среды. Также можно проверить реализацию данного класса на Github, чтобы увидеть, как он работает.
Readme
Каждый проект должен содержать файл Readme, в котором, по крайней мере, содержатся инструкции по установке зависимостей и запуску проекта. Он также должен содержать описания архитектуры проекта и модулей. К сожалению, разработчики не любят писать документацию (файл readme является частью этой работы), и я видел проект, который разрабатывался месяцами, и у него даже был файл Readme. Чтобы снять бремя написания файла readme, шаблон содержит стандартный файл readme, который охватывает установку и структуру проекта. При настройке нового проекта с использованием шаблонов, вы автоматически включаете файл Readme.
Gitignore
В настоящее время большинство проектов используют GIT в качестве системы контроля версий. При использовании GIT у разработчиков нет желания игнорировать некоторые файлы или папки в проекте, например папку сборки или папку производных данных. Чтобы избавить разработчика от необходимости поиска файла gitignore, подходящего для его проекта iOS, шаблон содержит стандартный gitignore, предоставленный участниками Github.
Базовые классы для обработки внешних ссылок и уведомлений
В настоящее время почти каждое приложение должно обрабатывать внешние ссылки и уведомления. Для этого разработчик должен написать некоторое количество стандартного кода в классе AppDelegate. В данном шаблоне имеется описание, как это выполнить, в нем также содержаться базовые классы, облегчающие работу с внешними ссылками и уведомлениями.
Автоматизируем сборку iOS приложений с помощью Fastlane
Как часто нам, iOS разработчикам, приходится собирать приложение для загрузки в iTunes Connect App Store Connect? В процессе этапа активного бета-тестирования приложения нужно оперативно фиксить баги и поставлять обновленную сборку для тестирования. А также необходимо скачивать сертификаты, Provision profiles, прокликивать много разных галочек и кнопочек при каждой выкладке нового билда.
К счастью, есть такой замечательный инструмент, как fastlane, который помогает нам автоматизировать ручные действия мобильного разработчика.
В этом посте я расскажу: что такое fastlane и как быстро начать его использовать в своих iOS проектах.
Введение
Что это?
Какой профит?
На первоначальную настройку базовых команд для автоматизации выкладки приложения, например, для публикации в App Store или на TestFlight, уйдет не более двух часов, однако в будущем это сэкономит уйму времени, т.к. весь процесс будет запускаться одним вызовом из командной строки.
ВНИМАНИЕ: Для выполнения всех шагов необходима подписка Apple Developer, так как доступ в App Store Connect отсутствует для бесплатных аккаунтов.
Установка
Устанавливаем сам fastlane
Для начала установим/обновим до последней версии Xcode Command Tools:
Устанавливаем gem fastlane:
Добавляем в проект
В корневой директории проекта запускаем:
Fastlane предложит нам варианты предустановленных скриптов в зависимости от того, что мы хотим:
Мы выберем 4 вариант, т.к. будем прописывать все необходимые команды под свою ситуацию:
Готово! Папка fastlane и файл gemfile успешно установлена к нам в проект.
Перед тем, как продолжим
Если в shell профайле locale не UTF-8, то будут возникать проблемы со сборкой и загрузкой билдов. Заходим в файл вашего shell profile (
/.zshrc) и добавляем следующие строчки:
Теперь все готово к написанию непосредственных шагов автоматизации сборки.
Как это работает
Для начала выясним, что делает fastlane: основные его команды и как мы описываем то, что нужно сделать.
Команды (Actions)
В fastlane входит много полезных команд, упрощающих жизнь разработчику:
Fastfile
Папка fastlane содержит в себе Fastfile и Appfile. В Appfile мы будем прописывать необходимые для сборки и публикации значения: Bundle IDs, App ID, Team ID и другие. В Fastfile мы будем описывать наши скрипты. После первоначальной установки он выглядит так:
Автоматизируем выгрузку на TestFlight
Начнем с задания понятного имени нашему lane’у. Переименуем custom_lane в testflight_lane. Теперь понятно, что результатом выполнения этого скрипта будет загруженная свежая сборка в TestFlight.
Конфигурируем Appfile
Для того, чтобы каждый раз при запуске скрипта не вводить bundle приложения и Apple ID, выпишем их в Appfile:
Сертификаты и Provision Profiles
Добавим команды cert и sigh для установки сертификатов и provision profiles соответственно:
(Внимание: если вашего приложения нет в App Store Connect, то необходимо добавить команду produce с параметром app_name)
Теперь сертификат и provision profiles скачены и установлены. Осталось проставить во вкладе General нужного таргета:
Сборка приложения
Добавим команду increment_build_number для увеличения номера билда. Если у вас главный .xcodeproj файл лежит не в корневой папке, то указываем для него путь в параметре xcodeproj:
Для работы увеличения номера билда, необходимо зайти в Build Settings/Versioning и выставить Versioning System в Apple Generic и Current Project Version в 1:
Добавим команду gym, которая собирает ipa файл нашего приложения:
Среди параметров можно указать, куда будет положен ipa (output_directory), имя ipa (output_name), scheme (scheme), делать ли Clean (clean) и некоторые другие. Мы ничего не будем указывать в параметрах — fastlane выставит параметры по-умолчанию, соберет и подпишет ipa, но опять же: при желании и необходимости всё можно указать подробно:
Выгрузка на TestFlight
Для загрузки ipa в TestFlight будем использовать Pilot:
С помощью Pilot можно:
Мы будем использовать основную его функцию: отправка сборок в Apple Store Connect.
Добавим в testflight_lane вызов upload_to_testflight с параметрами skip_submission (будем использовать только для загрузки ipa файла) и skip_waiting_for_build_processing (не дожидаемся окончания processing’a):
Запускаем итоговый скрипт
Сохраняем наши изменения и запускаем из консоли:
На этапе отправки в testflight в консоли потребуется ввести app-specific пароль (который требуется для авторизации в Application Loader). Найти его можно в личном кабинете Apple ID, сгенерировав его по нажатию на «Generate Password»:
После ввода пароля свежая сборка будет успешно загружена в TestFlight и выполнение fastlane на этом закончится:
Статус новой версии можно посмотреть в App Store Connect:
Заключение
На этом всё! Хотел бы обратить внимание, что в данной статье мы в самом общем случае попробовали возможности fastlane. В связи c этим прикрепляю опрос: будут ли интересны вам, хабровчане, посты про подробное использование упомянутых и других полезных команд в fastlane и продвинутых фишек в настройке скриптов?
Приложение с представленной настройкой fastlane можно найти здесь.
Особенности сборки и доставки iOS-приложений
В этой статье Максим Шестаков, DevOps Engineer в студии Plarium Krasnodar, делится опытом сборки и доставки пользователям приложений для iOS, который накопился в процессе отладки CI/CD.
Подготовка
Каждый человек, так или иначе связанный с разработкой приложений для устройств Apple, уже успел оценить спорное удобство инфраструктуры. Сложности встречаются повсюду: начиная с меню профиля разработчика и заканчивая инструментами отладки и сборки.
Статей об «азах» предостаточно в сети, поэтому постараемся выделить главное. Вот что нужно для успешной сборки приложения:
Основные типы профилей:
Для наглядности можно представить профиль разработчика в виде таблички ниже. Так проще понять, какие параметры для сборки нам нужны и откуда их брать.
Сборка
Существует два способа сборки файла *.ipa — устаревший (PackageApplication) и современный (через создание XcAchive и экспорт). Первый способ считается устаревшим, так как с версии 8.3 модуль упаковки app-файла убран из дистрибутива Xcode. Для его использования надо скопировать модуль из старого Xcode (версии 8.2 и более ранних) в папку:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/
И затем выполнить команду:
Далее нужно собрать *.app-файл приложения:
-workspace — путь к файлу проекта.
-scheme — используемая схема, указанная в проекте.
-derivedDataPath — путь выгрузки собранного приложения (*.app).
CODE_SIGN_IDENTITY — имя аккаунта разработчика, которое можно проверить в Keychain (iPhone Developer: XXXX XXXXXXX, без TeamID в скобках).
PROVISIONING_PROFILE — ID профиля для подписи приложения, который можно получить командой:
Если в приложении используется дополнительный профиль (например, для Push Notifications), то вместо PROVISIONING_PROFILE указываем:
Далее полученный файл *.app следует упаковать в *.ipa. Для этого можно использовать команду вида:
Однако данный способ считается устаревшим с точки зрения Apple. Актуальным является получение *.ipa путем экспорта из архива приложения.
Для начала нужно собрать архив командой:
Далее нам надо сгенерировать файл с настройками экспорта:
$Method — метод доставки, соответствует типу профиля подписи приложения, то есть для Development значение будет development, для Ad Hoc — ad-hoc, а для App Store — app-store.
$BundleID — ID приложения, который указан в настройках приложения. Проверить можно командой:
$TeamID — десятизначный ID в скобках после имени разработчика, пример: iPhone Developer: …… (XXXXXXXXXX); можно проверить в Keychain.
Далее с помощью команды экспорта получаем необходимый файл *.ipa:
Доставка
Теперь собранный файл нужно доставить конечному пользователю, то есть установить на устройство.
Для распространения билдов Development и Ad Hoc существует множество сервисов вроде HockeyApp, AppBlade и прочих, однако в рамках данной статьи речь пойдет об автономном сервере для раздачи приложений.
Установка приложения для iOS проходит в 2 этапа:
Как видим, манифест содержит практически все параметры, участвующие в сборке приложения.
Таким образом, для установки приложения достаточно простой html-страницы со ссылкой вида:
Для нужд отделов разработки и тестирования компания Plarium создала свое приложение установки билдов, которое дает нам:
Тестирование
Теперь речь пойдет о предрелизном тестировании приложения с помощью TestFlight.
Обязательными условиями для загрузки являются тип профиля подписи App Store и наличие сгенерированных API-ключей.
Есть несколько способов загрузки приложения:
Для получения API Key переходим по ссылке и генерируем ключ. Кроме самого ключа в формате *.p8, нам понадобятся два параметра: IssuerID и KeyID.
Далее скачанный ключ импортируем на билд-сервер:
Перед загрузкой приложения в TestFlight нужно выполнить валидацию приложения, делаем это командой:
Где apiKey и apiIssuer имеют значения полей со страницы генерации API-ключа.
Приложение будет проверено Apple в течение одного-двух дней и после станет доступным внешним тестировщикам: им пришлют на почту ссылки для установки.
Другим способом загрузки приложения через altool является использование App-Specific Password.
Для получения App-Specific Password нужно перейти по ссылке и сгенерировать его в разделе Security.
Далее следует создать в Keychain запись билд-сервера с этим паролем. С 11 версии Xcode это можно сделать командой:
$DeveloperName — имя аккаунта iOS-разработчика, используемое для логина в сервисы Apple.
$AppPswd — сгенерированный App-Specific Password.
Далее получаем значение параметра asc-provider и проверяем успешность импорта пароля командой:
Для валидации и загрузки приложения в TestFlight применяем команду:
Однако, как уже было сказано, с точки зрения работоспособности для авторизации altool лучше выбрать API Key, так как в разных версиях Xcode встречаются те или иные проблемы («не видит» Keychain, ошибки авторизации при выгрузке и прочее).
На этом, собственно, все. Желаю всем причастным успешных сборок и беспроблемных релизов в App Store.
Apple Configurator 2 4+
Apple
Снимки экрана
Описание
Apple Configurator 2 помогает легко выполнить развертывание iPad, iPhone, iPod touch и Apple TV в Вашей компании или учебном заведении.
С Apple Configurator 2 можно быстро сконфигурировать большое количество устройств, подключенных к Mac через USB, установив настройки, программы и данные для учащихся, сотрудников или покупателей.
Полностью обновленный Apple Configurator 2 с гибким интерфейсом, построенным вокруг устройств, позволяет быстро и легко сконфигурировать одно или десятки устройств. Просто выберите одно или несколько устройств и выполните действие. С Apple Configurator 2 Вы можете обновлять ПО, устанавливать программы и профили конфигурации, переименовывать и менять фоновые изображения на устройствах, экспортировать информацию и документы с устройств и многое другое. Вы также можете проверить любое устройство и просмотреть его данные, например серийный номер и аппаратные адреса, список установленных программ и профилей, а также журнал консоли.
Apple Configurator 2 совместно с Программой регистрации устройств позволяет автоматизировать развертывание MDM и Программу оптовой закупки, чтобы мгновенно распространять программы из App Store. Совершенно новый Ассистент подготовки позволяет легко контролировать и конфигурировать тележки с iPad в учебном классе и быстро выполнять развертывание большого количества устройств на сервере MDM для текущего управления. Встроенный редактор профилей конфигурации поддерживает создание и редактирование профилей с новейшими настройками iOS.
Если Вы конфигурируете устройства в среде, где важно единообразие, функция шаблонов позволяет создать любую конфигурацию и применять ее к устройствам одним нажатием. Шаблон — это виртуальное устройство, на которое можно добавлять профили конфигурации и программы, а также выполнять на нем действия, как на подключенном физическом устройстве.
Вы можете полностью автоматизировать Apple Configurator 2 и встроить его возможности в существующие процессы управления устройствами, используя встроенный инструмент командной строки, библиотеку скриптов AppleScript и действия программы Automator.
Поддержка iCloud Drive дает возможность сохранять единообразие профилей конфигурации и других настроек на нескольких станциях программы Configurator.