Налаштування 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 з високими вимогами до безпеки.







