GraphQL API с Swift: пошаговый туториал для iOS и macOS

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Почему GraphQL и Swift?

Современная iOS- и macOS-разработка требует гибких и эффективных способов взаимодействия с сервером. Традиционные REST API часто приводят к проблеме over-fetching (получение лишних данных) или under-fetching (недостаток данных). GraphQL решает эти проблемы, позволяя клиенту запрашивать только те данные, которые ему нужны, в одном запросе.

В этом туториале мы создадим полноценное приложение на Swift, которое будет взаимодействовать с GraphQL API. Вы узнаете, как настроить проект, выполнять запросы, мутации и обрабатывать ошибки. В качестве клиента мы будем использовать Apollo iOS — самую популярную библиотеку для работы с GraphQL в экосистеме Apple.

Настройка проекта и установка Apollo iOS

Создание нового проекта

Откройте Xcode и создайте новый проект iOS или macOS App. Назовём его GraphQLDemo.

Установка Apollo iOS через Swift Package Manager

  1. В Xcode перейдите в File → Add Packages...
  2. Вставьте URL репозитория Apollo: https://github.com/apollographql/apollo-ios.git
  3. Выберите последнюю стабильную версию и нажмите Add Package.
  4. Убедитесь, что пакет добавлен в target вашего приложения.

Генерация кода по схеме GraphQL

Apollo использует кодогенерацию для создания типобезопасных классов. Для этого нам нужен файл схемы (schema.graphqls) и файлы с запросами (.graphql).

Создайте папку GraphQL в проекте и поместите туда:

  • schema.graphqls — скачайте схему вашего API или используйте публичную (например, Countries GraphQL API).
  • Queries.graphql — файл с вашими запросами.

Пример содержимого Queries.graphql:

query GetCountries {
  countries {
    code
    name
    capital
    currency
  }
}

Теперь добавьте Build Phase для генерации кода. В Xcode: Target → Build Phases → + → New Run Script Phase. Вставьте скрипт:

cd "${SRCROOT}/${TARGET_NAME}"
./Pods/Apollo/scripts/run-bundled-codegen.sh codegen:generate --target=swift --includes=./**/*.graphql --localSchemaFile=./schema.graphqls ./GraphQL/API.swift

Примечание: В современных версиях Apollo iOS используется apollo-ios-cli. Рекомендуем ознакомиться с официальной документацией для актуальных инструкций.

Выполнение GraphQL запросов (Queries)

Инициализация Apollo клиента

Создадим менеджер для работы с Apollo. Откройте файл NetworkManager.swift:

import Foundation
import Apollo

class NetworkManager {
    static let shared = NetworkManager()
    
    private(set) lazy var apollo: ApolloClient = {
        let url = URL(string: "https://countries.trevorblades.com/")!
        return ApolloClient(url: url)
    }()
}

Выполнение запроса

Теперь выполним запрос GetCountries в нашем ViewController:

import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchCountries()
    }
    
    private func fetchCountries() {
        NetworkManager.shared.apollo.fetch(query: GetCountriesQuery()) { result in
            switch result {
            case .success(let graphQLResult):
                if let countries = graphQLResult.data?.countries {
                    for country in countries {
                        print("\(country.name) - \(country.capital ?? "N/A")")
                    }
                }
                if let errors = graphQLResult.errors {
                    print("GraphQL errors: \(errors)")
                }
            case .failure(let error):
                print("Network error: \(error)")
            }
        }
    }
}

Обратите внимание: Apollo автоматически генерирует типобезопасные классы (GetCountriesQuery), поэтому мы не работаем с сырыми JSON.

Обработка ошибок

Всегда проверяйте graphQLResult.errors — сервер может вернуть частичные данные с ошибками. Это особенность GraphQL.

Мутации (Mutations) и Подписки (Subscriptions)

Создание мутации

Добавим в Queries.graphql мутацию для добавления страны (если API поддерживает):

mutation AddCountry($code: String!, $name: String!) {
  addCountry(code: $code, name: $name) {
    code
    name
  }
}

Выполнение мутации:

func addCountry(code: String, name: String) {
    NetworkManager.shared.apollo.perform(mutation: AddCountryMutation(code: code, name: name)) { result in
        switch result {
        case .success(let graphQLResult):
            if let addedCountry = graphQLResult.data?.addCountry {
                print("Added: \(addedCountry.name)")
            }
        case .failure(let error):
            print("Mutation error: \(error)")
        }
    }
}

Подписки (Subscriptions) для реального времени

Подписки позволяют получать обновления в реальном времени через WebSocket. Для их использования требуется настроить транспорт WebSocket. Пример подписки:

// В файле .graphql
subscription OnCountryAdded {
  countryAdded {
    code
    name
  }
}

// В Swift коде
var cancellable: Cancellable?

func subscribeToNewCountries() {
    cancellable = NetworkManager.shared.apollo.subscribe(subscription: OnCountryAddedSubscription()) { result in
        switch result {
        case .success(let graphQLResult):
            if let country = graphQLResult.data?.countryAdded {
                print("New country: \(country.name)")
            }
        case .failure(let error):
            print("Subscription error: \(error)")
        }
    }
}

// Не забудьте отменить подписку, когда она больше не нужна:
cancellable?.cancel()

Важно: Для подписок Apollo iOS требует дополнительной настройки WebSocket транспорта. Подробнее — в документации Apollo Subscriptions.

Заключение: лучшие практики и дальнейшие шаги

Блоги

Рекомендаций по книгам