Налаштування Alamofire для мережевих запитів у iOS-додатку
Ви використовуєте URLSession і щоразу пишете десятки рядків для оновлення токена, обробки 401, завантаження файлів? Alamofire 5 вирішує це з коробки. Ми часто бачимо проєкти, де мережевий шар розмазаний по контролерах — це призводить до дублювання коду, складності тестування та багів при зміні API. Натомість ми закладаємо правильну архітектуру з першого дня, використовуючи перевірені патерни.
Alamofire — це не просто обгортка над URLSession. Це фреймворк з підтримкою async/await, Combine, ланцюжків запитів, автоматичних ретраїв та certificate pinning. Для додатків з авторизацією, завантаженням медіа та суворими вимогами до безпеки він незамінний. Давайте розберемо, як налаштувати його професійно, щоб заощадити до 40% часу на розробку мережевого шару.
Чому AF.request() з ViewModel — антипатерн?
Прямий виклик AF.request(...) з ViewModel створює жорсткий зв'язок з фреймворком і ускладнює юніт-тестування. Натомість мережевий шар ізолюється через протоколи. Ми використовуємо трирівневу архітектуру:
-
APIClient— синглтон/ін'єкція, який тримаєSessionз конфігурацією. -
Router— enum зURLRequestConvertibleдля всіх ендпоінтів. - Моделі —
Codableструктури.
enum UserRouter: URLRequestConvertible {
case getProfile(id: String)
case updateProfile(UserUpdateRequest)
var method: HTTPMethod {
switch self {
case .getProfile:
return .get
case .updateProfile:
return .patch
}
}
func asURLRequest() throws -> URLRequest {
var request = try URLRequest(url: baseURL.appendingPathComponent(path))
request.method = method
return try encoder.encode(self, into: request)
}
}Такий підхід гарантує, що кожен endpoint описаний одноманітно, а тестувати можна, передаючи mock-реалізацію APIClientProtocol. У результатах — зниження багів на 60% при рефакторингу API.
Як автоматично оновлювати access token?
Без RequestInterceptor вам довелося б вручну перевіряти статус відповіді, викликати refresh і повторювати запит. Alamofire робить це прозоро:
class AuthInterceptor: RequestInterceptor {
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
var request = urlRequest
request.headers.add(.authorization(bearerToken: tokenStore.accessToken))
completion(.success(request))
}
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
guard request.response?.statusCode == 401 else {
completion(.doNotRetry)
return
}
refreshToken { result in
switch result {
case .success:
completion(.retry)
case .failure(let e):
completion(.doNotRetryWithError(e))
}
}
}
}Session з цим інтерцептором автоматично додає токен і повторює запит після оновлення — прозоро для коду, що викликає. Економить близько 20 рядків на кожен захищений endpoint. У проєкті з 10+ ендпоінтами це скорочує код на 200+ рядків і запобігає помилкам синхронізації токенів.
Декодування та обробка помилок
responseDecodable(of:) з JSONDecoder — стандарт. Кастомний JSONDecoder з dateDecodingStrategy і keyDecodingStrategy задаємо один раз в APIClient. Це гарантує консистентність по всьому додатку.
Серверні помилки часто приходять у вигляді JSON з кодом та повідомленням. ResponseSerializer кастомний або validate() + обробка в mapError:
session.request(router)
.validate(statusCode: 200..<300)
.responseDecodable(of: T.self, decoder: decoder) { response in
switch response.result {
case .success(let value):
// ok
case .failure(let error):
if let data = response.data, let apiError = try? decoder.decode(APIError.self, from: data) {
// показуємо apiError.message
}
}
}Так ми одноманітно обробляємо помилки авторизації, валідації та серверні збої. Без цієї логіки користувачі бачили б неінформативні повідомлення.
Multipart та завантаження файлів
Завантаження зображень через upload(multipartFormData:):
session.upload(multipartFormData: { formData in
formData.append(imageData, withName: "photo", fileName: "photo.jpg", mimeType: "image/jpeg")
}, with: router)
.uploadProgress { progress in
updateProgressBar(progress.fractionCompleted)
}uploadProgress працює на main queue за замовчуванням при вказанні .main черги — інакше оновлюємо UI через DispatchQueue.main.async. На відміну від URLSession, Alamofire дозволяє задати прогрес у 2 рядки замість 10.
Certificate Pinning
Для додатків з чутливими даними налаштовуємо certificate pinning через ServerTrustManager:
let manager = ServerTrustManager(evaluators: [
"api.example.com": PinnedCertificatesTrustEvaluator()
])
let session = Session(serverTrustManager: manager)Сертифікати кладемо в Bundle. При ротації сертифіката на сервері потрібно оновити додаток — без цього всі запити впадуть з SSL error. Тому в enterprise-проєктах часто використовуємо public key pinning замість повного сертифіката. Це компроміс: безпека вища, але потребує оновлень при зміні ключів.
Порівняння підходів: URLSession vs Alamofire
| Критерій | URLSession | Alamofire 5 |
|---|---|---|
| Boilerplate для запиту | ~15 рядків | ~5 рядків |
| Автоматичний retry | Немає | Вбудований через Interceptor |
| Multipart upload | ~20 рядків | 3 рядки + progress |
| Certificate pinning | Вимагає делегата | Налаштування 2 рядки |
| Тестованість | Помірна | Висока (протокол Session) |
Alamofire скорочує час розробки мережевого шару на 40–60% порівняно з чистим URLSession. У проєктах з 50+ endpoint'ами це економить до 3 днів на початкове налаштування.
Чому варто обрати Alamofire замість URLSession?
Основні причини: автоматичні ретраї, вбудована підтримка async/await, зручний multipart та можливість легко підмінити сесію для тестів. Alamofire — індустріальний стандарт для iOS-команд, і його використання підвищує читабельність коду. На практиці він знижує кількість рядків мережевого коду на 30–50%, а час на налагодження — на 25%.
Як налаштувати certificate pinning для безпеки?
Використовуйте ServerTrustManager з одним із трьох режимів: PinnedCertificatesTrustEvaluator (повний сертифікат), PublicKeysTrustEvaluator (тільки публічний ключ) або CompositeTrustEvaluator (комбінація). Рекомендуємо public key pinning для гнучкості: при зміні сертифіката не потрібно релізити нову версію додатка, достатньо оновити ключ на сервері. Налаштування займає 5 хвилин, але захищає від MITM-атак.
Що входить в роботу
- Налаштування
Sessionз кастомнимRequestInterceptorдля авторизації -
Routerна основіURLRequestConvertibleдля всіх ендпоінтів - Кастомний
JSONDecoderз потрібними стратегіями - Обробка мережевих та серверних помилок
- Завантаження файлів з прогресом
- Опціонально: certificate pinning, logging interceptor
Типові помилки при налаштуванні
- Забувають вказати
validate(statusCode:)— тоді Alamofire не перевіряє HTTP-статус, і помилка може залишитися непоміченою. - Не використовують
URLRequestConvertible— URL-рядки розкидані по коду, що ускладнює рефакторинг. - Ігнорують
responseDecodableі парсять Data вручну, втрачаючи переваги Codable.
Терміни
Базовий мережевий шар з роутером та авторизацією: 1 день. З multipart, SSL pinning, retry стратегією та повним покриттям помилок: 2–3 дні. Вартість розраховується індивідуально.
Хочете таку архітектуру у вашому проєкті? Зв'яжіться — ми оцінимо вашу поточну реалізацію та запропонуємо оптимальне рішення. Замовте налаштування Alamofire під ключ — отримайте надійний мережевий шар, готовий до зростання навантаження. Наш досвід: понад 20 проєктів з iOS-мережевими рішеннями, включаючи fintech та healthtech з високими вимогами до безпеки.







