Всем привет! Сегодня мы создадим учебное приложение для iOS с использованием бэкенда на GraphQL  при помощи библиотеки Apollo — оно имеет несложный двухэкранный интерфейс, который не будет сильно отвлекать нас от работы с сетью. Приложение будет отображать прошедшие и грядущие запуски разных кораблей SpaceX. Приложение под названием Rocket Launch будет предоставлять информацию о миссиях, включая даты и время. Для создания Rocket Launch мы будем использовать UIKit без Сторибордов. В этом материале я дам код целиком с пояснениями, но оставляю ссылку на репозиторий со своим проектом. На главном экране будет отображаться список ракет в виде таблицы. При выборе ракеты будет открыт список прошедших и грядущих запусков этой ракеты. На экране списка запусков для каждого запуска будет отображаться дата и тип миссии. GraphQL — это язык запросов для работы с API, который позволяет клиентскому приложению запрашивать только нужные данные и получать их в формате JSON. GraphQL позволяет приложению точно специфицировать, какие данные нужны, и сервер возвращает только запрошенные данные. Это снижает объем передаваемых данных по сравнению с REST API и улучшает производительность приложения. Рекомендую ознакомиться с документацией на сайте GraphQL. Apollo — это библиотека для работы с GraphQL в клиентских приложениях. Она предоставляет удобные инструменты для запроса и мутации данных на сервере, а также для управления состоянием приложения. Библиотека Apollo интегрируется в том числе с iOS, именно её мы и будем использовать. Подробная информация также доступна на сайте библиотеки. SpaceXAPI — хороший тренировочный API. Там мы получим URL, по которому будем осуществлять запросы, нужную нам GraphQL-схему, а также поработаем в разделе Explorer. В нём мы сможем создавать необходимые нам операции, сражу же выполнять их и смотреть, что приходит в ответе. Для начала создадим проект нового приложения в Xcode. Я назвал его rocket-launch-programmatically, так как собираюсь создавать его в коде без использования Storyboard. Выбираем интерфейс Storyboard и выбираем язык Swift. Теперь установим Apollo. Это можно сделать разными способами, например через CocoaPods или Package Manager. Я выберу второй вариант. В поиске вводим apollo-ios и устанавливаем фреймворк. Нам достаточно установить первый Package Product в списке — Apollo. CLI (Command Line Interface) поможет нам генерировать Swift-код на основе схемы GraphQL. Для этого нам нужно открыть контекстное меню на нашем проекте, сделав правый клик в левом верхнем углу Xcode и выбрать Install CLI, после этого нажимаем Run и даём разрешение на изменение файлов. Зайдём в Terminal и выполним команду для перехода в папку нашего проекта. В моём случае он лежит прямо на Десктопе. cd Desktop/rocket-launches-programmatically Теперь проинициализируем файл конфигурации. Этот файл определяет необходимый набор параметров для дальнейшей генерации кода. В команду init нам нужно передать значение для аргумента schema-name (это пространство имён для будущих сгенерированных файлов) и значение для аргумента  module-type — swiftPackageManager. Это значит, что все будущие файлы будут связаны с основным проектом через SPM. ./apollo-ios-cli init --schema-name SpaceXAPI --module-type swiftPackageManager После выполнения команды будет создан файл конфигурации. Теперь нам нужно загрузить файл схемы, где описаны все возможные запросы, типы и структуры данных. Для этого нам нужно открыть вкладку с нашим SpaceXAPI. На странице в левом меню выбираем раздет Schema, затем переходим в SDL. Вот прямая ссылка на этот раздел. Нам нужно загрузить файл Raw в правой верхней части страницы. NB Любопытный момент, что файл скачивается в расширении .graphql. Оно подходит только для query, мутаций и фрагментов. Для того, чтобы использовать файл в качестве схемы, нужно изменить расширение на .graphqls (s в конце как раз означает schema). Само имя файла для удобства переименуем в schema, то есть в итоге мы получаем файл schema.graphqls. Для удобства создадим в нашем проекте папку GraphQL и перенесем нашу схему туда. Теперь внесём папку в наш проект, сделав правый клик в Navigator area и добавив в проект папку GraphQL. На первом экране нашего приложения будет отображаться список ракет компании SpaceX. Мы снова отправимся на сайт SpaceX API и перейдём в раздел Explorer. Там мы создадим query, которая и будет возвращать список ракет. В левой навигационной панели нам нужно найти позицию rockets (не путать с Rocket, нам нужен массив). Нажав на неё, мы получаем новую query в редакторе. Теперь найдём в навигаторе и добавим поля, которые мы хотим получить в запросе. Точно так же выберем поля id, name, heigh (отметим только метры) и массу (отметим только килограммы). Прямо в редакторе кода переименуем операцию Rockets в RocketsQuery. Если мы нажмём на тестовый запуск, то в инспекторе справа увидим данные о разных ракетах. Теперь прямо в папке GraphQL в Xcode создадим файл rocketsQuery с расширением .graphql. При выборе типа файла берем темплейт Empty. Прямо в него копируем нашу только что созданную query. Вот здесь нам и понадобится упомянутый выше CLI. Нам нужно снова перейти в Terminal и выполнить команду generate. Это необходимо делать каждый раз при изменениях существующих операций и при добавлении новых. Вот её код для Терминала: ./apollo-ios-cli generate После этого в папке SpaceXAPI появится файл RocketsQuery.graphql с расширением .swift. Мы сгенерировали graphql-модуль, и теперь нужно добавить в наш проект локальный пакет SpaceXAPI. Для этого нам нужно открыть Package Manager и нажать кнопку Add Local… в нижней части интерфейса. Там нам нужно выбрать папку SpaceXAPI и нажать Add Package. Также добавим SpaceXAPI в раздел Frameworks нашего основного таргета. После этого можно импортировать пакет в любой файл через import SpaceXAPI Создадим простой клиент под названием NetworkService. Это будет swift-файл с синглтоном. У него всего одно свойство Apollo, и к нему мы будем обращаться всегда, когда захотим выполнить какую-то GraphQL-операцию. Свойство Apollo нам нужно проинициализировать с каким-либо end point, куда будут отправляться запросы. Мы возьмём URL из документации SpaceXAPI. Вот код для нашего NetworkService: Чтобы сразу отключить Сториборд, допишем функцию scene в SceneDelegate и сделаем нашим рутовым контроллером RocketsViewController, который мы вскоре создадим. Разумеется, можно сделать это через AppDelegate, а также опционально удалить файл Main и всё, что связано со Сторибордом. Я не буду вдаваться в детали работы с UITableView. Скорее всего, вы с ним хорошо знакомы. Поэтому не буду давать исчерпывающих объяснений по созданию таблицы и ячеек, а просто покажу код с комментариями. Для контроллера RocketsViewController я создал отдельный одноимённый файл. В TableView будет прокидываться ячейка RocketCell, для которой я создал отдельный файл. Для читаемости кода я использую кложурную инициализацию, а также функции setupViews() для иерархии вью и setupConstraints() для настройки лейаута при помощи библиотеки SnapKit — я загрузил его через SPM. Собственно, давайте перейдём к тому, ради чего мы тут собрались. Создадим новый файл Swift под названием RocketsViewController. Нам нужно не забыть импортировать локальный пакет SpaceXAPI, которые мы создали ранее. Кроме того, я импортирую библиотеку SnapKit для работы с констрейнтами. Далее создаём класс нашей таблицы на вью контроллере RocketsViewController: Далее сделаем расширение класса и настроим delegate и dataSource нашей таблицы. Теперь допишем ещё одно расширение класса для функции, которая будет приносить данные о ракетах: В отдельном файле создадим ячейку RocketCell В многом алгоритм создания GraphQL-операции и вью контроллера для отображения запусков каждой ракеты идентичен тому, что мы уже собрали, но с некоторыми нюансами. Давайте вернёмся на сайт нашего SpaceXAPI и создадим новую операцию, которая сможет приносить нам данные и совершённых и планируемых запусках отдельных ракет. Тут стоит обратить внимание на ещё одну удобную особенность GraphQL: мы можем выполнять две разных операции в рамках одной общей. Сейчас мы в этом убедимся — в нашем случае это две операции — одна для получения информации о прошлых запусках, вторая — о грядущих. Вот как будет выглядеть готовый код: В эксплорере на сайте API создадим новую вкладку, в навигаторе слева выберем launchesUpcoming, после чего в открывшемся меню выберем значения id, mission_name и launch_date_utc. Теперь нажмём в навигаторе стрелку назад и добавим операцию для получения будущих запусков. Выберем поле launchesPast и положим туда те же значения d, mission_name и launch_date_utc. Переименуем общую операцию (сейчас она называется LaunchesUpcoming) в LauchesQuery. Так как мы хотим получать запуски по конкретной ракете, нам нужно добавить два параметра для каждой из query. Это параметр find, в который можно передать id ракеты. Теперь вернёмся в Xcode и создадим новый файл типа Empty в нашей папке GraphQL. Он будет называться launchesQuery.graphql. Добавим в этот файл наш GraphQL-код с описанием операции. Вот как это должно выглядеть: Помните, что обязательно нужно сделать теперь? Правильно, необходимо сгенерировать swift-файл. Для этого возвращаемся в Terminal и снова вводим команду: ./apollo-ios-cli generate Если в нашей папке сгенерировался новый файл с расширением .swift, всё в порядке. Новый вью-контроллер LaunchesViewController будет отображаться через present при нажатии на одну из ячеек таблицы (конкретная ракета) на нашем первом вью-контроллере. Именно для этого в конце того файла мы заранее написали функцию didSelectRowAt — func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) (сейчас она закомментирована). Итак, создадим новый Swift-файл под названием LaunchesViewController, импортируем туда необходимые библиотеки. Теперь напишем код класса LaunchesViewController. Добавим расширение класса для конфигурации таблицы. Как говорил ранее, не буду фокусироваться на особенностях создания UITableView. Вот код самого вьконтроллера: Расширения контроллера для работы с ячейкой, которую мы создадим далее: Создадим ещё одно расширение класса для метода по получению запусков через Apollo. Наконец, создадим новый Swift-файл для ячейки запусков под названием LaunchCell. После всех этих действий приложение должно корректно работать.  iOS-разработчик