Начало работы с Alamofire

Чтобы начать интеграцию Alamofire в ваш проект iOS, вы можете добавить библиотеку с помощью Swift Package Manager, CocoaPods или Carthage. Swift Package Manager является рекомендуемым подходом, поскольку он встроен в Xcode. Добавить пакет Alamofire, перейдя в FileAdd Packages и введя URL-адрес репозитория . Укажите версию 5.0.0 или более поздней. Альтернативно, если вы используете CocoaPods, добавьте в свой Podfile и запустите . После интеграции зависимости импортируйте Alamofire в любой файл Swift, где вам нужна сетевая функциональность:

import Alamofire

Alamofire's псевдоним обеспечивает удобную точку входа для всех распространенных операций HTTP. Под капотом он использует Apple , но абстрагирует от шаблона, такого как управление очередями, кодирование параметров и проверка ответа. Это позволяет сосредоточиться на бизнес-логике, а не на сетевой сантехнике. Для получения дополнительной информации о базовом сетевом уровне обратитесь к документации Apple URLSession .

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

Получение данных с конечной точки RESTful является наиболее распространенной операцией. Alamofire делает запросы GET краткими и читаемыми. Следующий пример извлекает список пользователей из гипотетического API:

AF.request("https://api.example.com/users")
 .validate()
 .responseDecodable(of: [User].self) { response in
 switch response.result {
 case .success(let users):
 print("Fetched \(users.count) users")
 case .failure(let error):
 print("Request failed with error: \(error)")
 }
 }

Обратите внимание на использование протокола Swift , который использует протокол Swift для автоматического разбора JSON на объекты модели. Определите структуру , которая соответствует (или ). Этот подход устраняет ручную сериализацию JSON и повышает безопасность типов.

Добавление параметров запросов и заголовков

Многие REST API требуют параметров запроса или пользовательских HTTP-заголовков. Alamofire принимает параметры в качестве словаря и автоматически обрабатывает кодирование запросов GET (параметры добавлены к URL). Заголовки добавляются через параметр :

let parameters: Parameters = ["page": 1, "limit": 20]
let headers: HTTPHeaders = [
 "Authorization": "Bearer YOUR_TOKEN",
 "Accept": "application/json"
]

AF.request("https://api.example.com/users",
 parameters: parameters,
 headers: headers)
 .validate()
 .responseDecodable(of: [User].self) { response in
 // handle response
 }

Alamofire автоматически кодирует параметры и прикрепляет их к URL-адресу запроса. Для пользовательского кодирования вы можете указать явный экземпляр , такой как .

Проверка ответов

Метод автоматически проверяет коды состояния HTTP в диапазоне 200—299 и отклоняет ответы с неприемлемым типом контента. Также можно добавить пользовательские критерии проверки. Например, принимать только коды состояния 200 и 201:

.validate(statusCode: [200, 201])

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

Отправка данных POST

Создание или обновление ресурсов обычно требует запроса POST с телом запроса. Alamofire поддерживает несколько стратегий кодирования, причем является наиболее распространенным для REST API. Следующий пример отправляет новый пользовательский объект на сервер:

let newUser: [String: Any] = [
 "name": "Jane Doe",
 "email": "[email protected]"
]

AF.request("https://api.example.com/users",
 method: .post,
 parameters: newUser,
 encoding: JSONEncoding.default)
 .validate()
 .responseDecodable(of: User.self) { response in
 switch response.result {
 case .success(let createdUser):
 print("User created: \(createdUser)")
 case .failure(let error):
 print("Error creating user: \(error)")
 }
 }

Если API ожидает данные формы, кодируемые URL (например, для обмена токенами OAuth), используйте вместо этого. Для загрузки файлов или смешанных данных Alamofire предоставляет , который создает многочастный запрос. Пример:

AF.upload(multipartFormData: { multipartFormData in
 multipartFormData.append(Data("Jane Doe".utf8), withName: "name")
 multipartFormData.append(imageData, withName: "avatar", fileName: "avatar.jpg", mimeType: "image/jpeg")
}, to: "https://api.example.com/users")
 .validate()
 .responseDecodable(of: User.self) { response in
 // handle response
 }

Работа с другими HTTP-методами

RESTful API часто требуют PUT (полное обновление), PATCH (частичное обновление) и DELETE (удаление). Alamofire обрабатывает их одним и тем же методом ; просто измените параметр .

Вставить и ставить

Для обновления существующего ресурса используйте или . Орган запроса содержит обновленные поля:

let updatedFields: [String: Any] = ["name": "Jane Smith"]
AF.request("https://api.example.com/users/123",
 method: .patch,
 parameters: updatedFields,
 encoding: JSONEncoding.default)
 .validate()
 .responseDecodable(of: User.self) { response in
 // handle updated user
 }

Удалить

Удаление ресурса обычно не требует наличия органа запроса. Ответ может быть пустым или может быть возвращено сообщение с подтверждением:

AF.request("https://api.example.com/users/123",
 method: .delete)
 .validate()
 .response { response in
 if let error = response.error {
 print("Delete failed: \(error)")
 } else {
 print("User deleted successfully")
 }
 }

Всегда проверяйте документацию API на наличие кодов состояния (например, 204 No Content).

Усовершенствованная обработка ошибок и мониторинг сети

Надежная обработка ошибок имеет решающее значение для бесперебойного взаимодействия с пользователем. Alamofire сообщает об ошибках по типу , который различает сетевые ошибки (тайм-аут, отсутствие соединения), ошибки сервера (код плохого состояния) и сбои сериализации (недействительный JSON). Вы можете проверить ошибку, чтобы предоставить конкретную обратную связь:

switch response.result {
case .success(let value):
 // handle success
case .failure(let error):
 if let afError = error.asAFError {
 switch afError {
 case .sessionTaskFailed(let sessionError):
 print("Network issue: \(sessionError.localizedDescription)")
 case .responseValidationFailed(let reason):
 print("Validation failed: \(reason)")
 default:
 print("Other Alamofire error: \(afError.localizedDescription)")
 }
 }
}

Сетевая доступность

Перед тем, как делать запросы, вы можете проверить доступность сети. Alamofire отслеживает изменения подключения. Начните мониторинг в начале жизненного цикла вашего приложения:

let reachabilityManager = NetworkReachabilityManager()
reachabilityManager?.startListening { status in
 switch status {
 case .notReachable:
 print("Network is not reachable")
 case .reachable(.cellular):
 print("Connected via cellular")
 case .reachable(.ethernetOrWiFi):
 print("Connected via WiFi")
 case .unknown:
 print("Unknown status")
 }
}

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

Лучшие практики для создания сетей производственного уровня

Следуя установленным шаблонам, ваш сетевой уровень будет поддерживаться, оставаться безопасным и работоспособным.

1.Принять кабельные модели

Всегда определяйте типы Swift, которые соответствуют (или )] для анализа ответов. Это устраняет ручные манипуляции JSON и уменьшает ошибки. Используйте или более низкий уровень , если вам нужен динамический контент. Кодируемое руководство Apple охватывает расширенное отображение с помощью пользовательских ключей.

2.Более безопасная аутентификация и управление токенами

Никогда не ставьте ключи API или токены. Храните чувствительные значения в Keychain и прикрепляйте их к запросам через заголовок . Для потоков OAuth реализуйте перехватчик обновления токенов. Протокол Alamofire позволяет автоматически перезаписывать запросы после получения нового токена. Образец скелета:

class AuthInterceptor: RequestInterceptor {
 func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
 var request = urlRequest
 request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
 completion(.success(request))
 }

 func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
 // Check if error is 401, refresh token, then retry
 completion(.retryWithDelay(1.0))
 }
}

3. Соответствие с асинком/ожиданием

Alamofire 5 полностью поддерживает параллельную модель Swift. Используйте версии методов запроса для написания более чистого линейного кода:

do {
 let users = try await AF.request("https://api.example.com/users")
 .serializingDecodable([User].self)
 .value
 print("Users: \(users)")
} catch {
 print("Error: \(error)")
}

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

4. Внедрить кэширование

Для уменьшения количества сетевых вызовов и улучшения поддержки в автономном режиме настройте политики кэширования. Alamofire уважает (например, ). Вы также можете использовать пользовательский с соответствующей емкостью диска:

let cache = URLCache(memoryCapacity: 10 * 1024 * 1024,
 diskCapacity: 50 * 1024 * 1024,
 diskPath: "networking_cache")
let session = Session(configuration: URLSessionConfiguration.default)
session.sessionConfiguration.urlCache = cache

5.Проверить свой сетевой уровень

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

6. Используйте централизованный сетевой менеджер

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

class APIClient {
 static let shared = APIClient()
 private let session: Session

 private init() {
 let config = URLSessionConfiguration.default
 config.timeoutIntervalForRequest = 30
 config.urlCache = URLCache.shared
 session = Session(configuration: config, interceptor: AuthInterceptor())
 }

 func fetchUsers() async throws -> [User] {
 return try await session.request("\(baseURL)/users")
 .serializingDecodable([User].self)
 .value
 }
}

Для всестороннего понимания сетевых моделей обратитесь к документации по расширенному использованию Alamofire . Кроме того, учебник API REST на restfulapi.net предлагает ценную информацию о разработке надежных API.

Следуя этим рекомендациям и используя выразительный API Alamofire, вы можете создать сетевой слой, который одновременно является мощным и простым в обслуживании. Библиотека абстрагирует многие утомительные аспекты загрузки URL-адресов, предоставляя вам полный контроль, когда вам это нужно.