Apollo iOS: Мощный GraphQL клиент для Swift-приложений
Apollo iOS — это современная, типобезопасная библиотека для работы с GraphQL API на платформах Apple: iOS, macOS, tvOS и watchOS. Разработанная компанией Apollo GraphQL, она предоставляет разработчикам удобные инструменты для выполнения запросов, мутаций и подписок, автоматически генерируя строго типизированный код на Swift на основе вашей GraphQL-схемы.
Библиотека идеально подходит для создания современных мобильных и десктопных приложений, где требуется гибкая работа с данными, кэширование и высокая производительность. Apollo iOS избавляет от ручного парсинга JSON и обеспечивает полную безопасность типов на этапе компиляции.
Основные возможности
- Автоматическая генерация кода — на основе .graphql-файлов и схемы сервера создаются типизированные модели данных, запросы и мутации.
- Нормализованное кэширование — встроенный кэш автоматически обновляет UI при изменении данных, избегая дублирования объектов.
- Поддержка подписок через WebSocket — real-time обновления для чатов, уведомлений и других динамических данных.
- Интеграция с SwiftUI и Combine — нативные асинхронные Publisher и ObservableObject для реактивного программирования.
- Многопоточность — все сетевые запросы выполняются в фоне, основной поток остаётся свободным для UI.
- Поддержка загрузки файлов — работа с multipart-запросами для отправки изображений и документов.
Установка через Swift Package Manager
Добавьте Apollo iOS в ваш проект через Xcode или Package.swift:
// Package.swift
dependencies: [
.package(url: "https://github.com/apollographql/apollo-ios.git",
from: "1.0.0")
]
Пример: настройка клиента и выполнение запроса
Создадим экземпляр клиента и выполним простой GraphQL-запрос для получения списка пользователей:
import Apollo
// 1. Создаём клиент
let url = URL(string: "https://api.example.com/graphql")!
let store = ApolloStore()
let client = ApolloClient(url: url, store: store)
// 2. Определяем запрос (файл Users.graphql)
// query GetUsers { users { id name email } }
// 3. Выполняем запрос
client.fetch(query: GetUsersQuery()) { result in
switch result {
case .success(let graphQLResult):
if let users = graphQLResult.data?.users {
for user in users {
print("\(user.name) — \(user.email)")
}
}
case .failure(let error):
print("Ошибка: \(error.localizedDescription)")
}
}
Работа с мутациями (изменение данных)
Пример мутации для создания нового пользователя:
// mutation CreateUser($name: String!, $email: String!) {
// createUser(name: $name, email: $email) { id name email }
// }
let mutation = CreateUserMutation(name: "Иван Петров",
email: "ivan@example.com")
client.perform(mutation: mutation) { result in
switch result {
case .success(let graphQLResult):
if let newUser = graphQLResult.data?.createUser {
print("Создан пользователь: \(newUser.id)")
}
case .failure(let error):
print("Ошибка создания: \(error)")
}
}
Подписки (real-time обновления)
Для получения данных в реальном времени используйте подписки. Требуется WebSocket-транспорт:
import ApolloWebSocket
let webSocketTransport = WebSocketTransport(
request: URLRequest(url: URL(string: "wss://api.example.com/graphql")!)
)
let store = ApolloStore()
let client = ApolloClient(networkTransport: webSocketTransport,
store: store)
// subscription OnUserAdded { userAdded { id name } }
let subscription = client.subscribe(subscription: OnUserAddedSubscription()) { result in
switch result {
case .success(let graphQLResult):
if let newUser = graphQLResult.data?.userAdded {
print("Новый пользователь: \(newUser.name)")
}
case .failure(let error):
print("Ошибка подписки: \(error)")
}
}
Интеграция с SwiftUI
Библиотека отлично работает с современным фреймворком SwiftUI. Используйте @Published и ObservableObject:
import SwiftUI
import Apollo
class UsersViewModel: ObservableObject {
@Published var users: [User] = []
private var cancellables = Set<AnyCancellable>()
func loadUsers() {
client.fetch(query: GetUsersQuery())
.map { $0.data?.users ?? [] }
.replaceError(with: [])
.assign(to: &$users)
}
}
struct UsersListView: View {
@StateObject private var viewModel = UsersViewModel()
var body: some View {