iOS проект лучшие практики и инструменты

С шаблоном проекта Xcode с открытым исходным кодом

При работе над новыми проектами iOS мне часто приходилось начинать новый проект с нуля. При этом я и моя команда всегда тратили много времени на базовые настройки проекта, такие как интеграция инструментов, настройка структуры проекта, написание базовых классов, интеграция внешних библиотек и т. Д.

Я решил, что время, затрачиваемое на запуск проекта, можно сэкономить, а процесс можно в основном автоматизировать. Я записал все обычные лучшие практики и инструменты, которые мы использовали, и подготовил шаблон проекта, который я и моя команда могли бы использовать при запуске новых проектов. Этот шаблон должен сэкономить время на настройку проекта, а также обеспечить общую основу, к которой привыкнет каждый член команды, чтобы вам не приходилось думать и изучать структуру и основы проекта. Они всегда будут одинаковыми.

Каждый инструмент или лучшая практика, включенные в шаблон, заслуживают отдельной статьи, но я хотел бы попытаться суммировать каждый пункт и дать краткое объяснение, почему я включил их.

Cocoapods

Я не думаю, что это нужно введение. Это библиотека для управления внешними зависимостями для проектов iOS. Он существует уже давно и является надежным и испытанным в сражениях в тысячах (если не в миллионах) проектов. Существуют альтернативные менеджеры зависимостей, такие как Carthage, но я решил пойти с Cocoapods, потому что у него самый широкий спектр поддерживаемых проектов с открытым исходным кодом. Использовать Cocoapods очень просто, и он поставляется с поисковым индексом, который позволяет легко находить пакеты, которые могут вам понадобиться.

Проект шаблона поставляется с простым Podfile, который включает Swiftlint и R.swift. Шаблон также включает Gemfile для управления версией Cocoapods, используемой для разрешения зависимостей. Это часто пропускаемое улучшение, которое предотвращает проблемы, возникающие, когда разработчики в вашей команде устанавливают зависимости, используя разные версии Cocoapods. Gemfile принудительно использует одну и ту же версию Cocoapods во всей команде.

Swiftlint

Swiftlint - это очень полезный инструмент для обеспечения соблюдения определенных правил и стиля кодирования для каждого программиста в команде. Вы можете думать об этом как об автоматизированной системе проверки кода, которая предупреждает программиста об опасных вещах, таких как принудительное развертывание, принудительное приведение, принудительное выполнение и т. Д., Но также применяет общий стиль кодирования, следя за тем, чтобы все программисты следовали одинаковым правилам, связанным с «стилем кода». как отступы или интервалы. Это имеет огромные преимущества не только экономит время на проверку кода, выполняя эти основные проверки, но также делает все файлы в проекте выглядящими знакомыми, что повышает их читаемость и, как следствие, их понимание всеми разработчиками. Вы можете найти список всех правил здесь. В шаблоне Swiftlint устанавливается через Cocoapods и включается в шаг фаз сборки, поэтому он предупреждает разработчика при каждой сборке проекта.

R.swift

R.swift - это инструмент для получения строго типизированных, автозаполненных ресурсов, таких как изображения, сегменты шрифтов и локализации. Это делается путем сканирования вашего проекта и генерации быстрых классов, необходимых для получения ресурсов. Самым большим преимуществом этой библиотеки является то, что при использовании ресурсов она создает ваш код:

  • Полностью набрано - меньше приведения и угадывание метода
  • Время компиляции проверено - больше нет неправильных строк, которые приводят к сбою приложения во время выполнения
  • Автозаполнение - никогда больше не нужно угадывать имя этого изображения / пера / раскадровки

Рассмотрим следующий код с использованием официального строкового API:

let icon = UIImage (названный: «custom-icon»)

Если вы ошиблись в названии изображения, вы получите ноль здесь. Если какой-либо член вашей команды изменит имя ресурса изображения, этот код вернет ноль или вылетит, если вы принудительно развернете изображение. При использовании R.swift это становится:

let icon = R.image.customIcon ()

Теперь вы можете быть уверены, что значок действительно существует (компилятор предупредит вас, если этого не произойдет благодаря проверкам времени компиляции), и вы уверены, что вы не сделаете опечатку в имени значка, так как будете использовать автозаполнение.

R.swift устанавливается через Cocoapods и интегрируется в шаблон в качестве фазы сборки и будет генерировать классы оболочки Swift для каждой сборки. Это означает, что если вы добавите файл / изображение / локализация / шрифт / цвет / перо и т. Д., То он будет доступен вам с помощью R.swift после компиляции проекта.

Отдельный AppDelegate для тестов

Хорошей практикой часто забывают иметь отдельный класс TestAppDelegate при запуске тестов. Почему это хорошая идея? Ну, обычно класс AppDelegate выполняет много работы при запуске приложения. Он может настроить окно, построить базовую структуру пользовательского интерфейса приложения, зарегистрироваться для уведомлений, настроить базу данных и даже иногда делать вызовы API для некоторой серверной службы. Модульные тесты не должны иметь побочных эффектов. Вы действительно не хотите делать случайные вызовы API и настраивать всю структуру пользовательского интерфейса вашего приложения только для запуска некоторых модульных тестов?

TestAppDelegate также является отличным местом для того, чтобы иметь код, который вы хотите запускать только один раз во время выполнения набора тестов. Он может содержать код, который генерирует макеты, заглушки сетевых запросов и т. Д.

Шаблон содержит файл main.swift, который является основной точкой входа для приложения. В этом файле есть методы, которые проверяют, в какой среде приложение работает в данный момент, и, если это тестовая среда, вызывает TestAppDelegate.

Флаги профилирования производительности компилятора

Swift - отличный язык, более простой в использовании и намного более безопасный, чем Objective-C (IMO). Но когда он был впервые представлен, у него был один большой недостаток - время компиляции. Вернувшись в Swift 2 дня, я работал над проектом, в котором было примерно 40 тыс. Строк кода Swift (проект среднего размера). Код был очень тяжелым, с обобщениями и выводом типов, и компиляция чистой сборки заняла около 5 минут. Когда вы вносите даже небольшие изменения, проект перекомпилируется и занимает около 2 минут, чтобы увидеть изменения. Это был один из худших событий, которые я когда-либо испытывал, и из-за этого я почти прекратил использовать Swift.

Тогда единственным решением было попытаться профилировать время компиляции проекта и попытаться изменить свой код таким образом, чтобы компилятор работал быстрее. Чтобы помочь с этим, Apple вводит некоторые неофициальные флаги компилятора, которые предупреждают вас, когда компиляция тела метода или определение типа выражения занимает слишком много времени. Я добавил эти флаги в проект шаблона, чтобы вы с самого начала предупреждали о длительном времени компиляции для вашего приложения.

В настоящее время время сборки значительно улучшилось, и вам очень редко приходится настраивать свой код только для того, чтобы улучшить время сборки. Но все же лучше знать заранее, чем пытаться решить проблему, когда проект становится слишком большим.

Dev / Staging / Производственные конфигурации

Еще одна хорошая практика (или, можно сказать, необходимость) - это иметь отдельные конфигурации и переменные среды для сред разработки, промежуточных и производственных сред. В настоящее время почти каждое приложение должно подключаться к какой-либо серверной службе, и обычно эти службы развертываются в нескольких средах. Среда разработки используется для ежедневного развертывания и для разработчиков для тестирования своего кода. Промежуточная среда используется для стабильных выпусков для тестирования тестерами и клиентами. Мы все знаем, для чего нужна производственная среда.

Одним из способов поддержки нескольких сред в проекте iOS является добавление конфигураций на уровне проекта.

Конфигурации уровня проекта

После того как вы определили конфигурации, вы можете создать файл Configuration.plist, содержащий переменные для каждой среды.

Configuration.plist

При запуске проекта вы можете указать, какую конфигурацию следует использовать. Вы можете сделать это в схеме сборки.

Затем вам нужно добавить еще одно свойство в файл проекта Info.plist. Значение этого свойства будет динамически разрешаться во время выполнения в имя текущей конфигурации.

Это все предварительно настроено для вас в шаблоне.

Осталось только написать класс, который может извлекать эти переменные во время выполнения в зависимости от конфигурации, выбранной в схеме сборки. Шаблон содержит класс ConfigurationManager, который может извлекать переменные для текущей среды. Вы можете проверить реализацию этого класса на Github, чтобы увидеть, как он работает.

Прочти меня

Каждый проект должен иметь базовый файл Readme, в котором, по крайней мере, содержатся инструкции по установке зависимостей и запуску проекта. Он также должен содержать описания архитектуры проекта и модулей. К сожалению, разработчики не любят писать документацию (readme является частью этого), и я видел проект, который разрабатывался месяцами, и у него даже был базовый Readme. Чтобы снять бремя написания этого базового файла readme, шаблон содержит стандартный файл readme, который охватывает установку и структуру проекта. Когда вы настраиваете новый проект с использованием шаблона, вы автоматически включаете файл Readme.

Gitignore

В настоящее время большинство проектов используют GIT в качестве системы контроля версий. При использовании GIT вы обычно не хотите игнорировать некоторые файлы или папки в проекте, например папку сборки или папку производных данных. Чтобы избавить вас от необходимости поиска файла gitignore, подходящего для вашего проекта iOS, шаблон включает в себя стандартный gitignore, предоставленный участниками Github.

Базовые классы для обработки глубоких ссылок и уведомлений

В настоящее время почти каждое приложение должно обрабатывать глубокие ссылки и уведомления. Для этого разработчик должен написать некоторое количество стандартного кода в классе AppDelegate. В шаблоне это описано, а также предоставляет базовые классы, облегчающие работу с глубокими ссылками и уведомлениями.

Резюме

Подводя итог, шаблон пытается включить лучшие практики и интегрирует полезные сторонние инструменты. Это должно сэкономить вам и нашей команде часы, потраченные на настройку нового проекта, а также обеспечить общую и прочную основу для остальной части проекта. Пусть это послужит вам хорошо!

PS: Если у вас есть какие-либо проблемы или пожелания по шаблону, просто оставьте мне проблему на Github. Я постараюсь решить это в свое свободное время.