Как обрабатывать результат запроса с success и failure в iOS
Что проверяют
Умеете ли вы довести сетевой запрос до понятного результата: отличить ошибку транспорта от плохого HTTP-статуса и от сбоя декодирования и не сломать при этом UI. Следом обычно просят переписать то же самое на async/await.
Как отвечать
Для колбэков стандартный тип Result<Success, Failure>: вызывающий код обязан обработать обе ветки через switch. Хороший каркас выглядит так:
- своя ошибка:
enum NetworkError: Error { case transport(URLError), badStatus(Int), decoding(Error) }. ТипизированныйFailureпозволяет UI по-разному реагировать на отсутствие сети и на ответ 500; - проверка статуса: в
dataTaskпараметрerrorравенnilи на 404, и на 500. Код берётся из(response as? HTTPURLResponse)?.statusCodeи сверяется с200..<300; - ровно один вызов: каждая ветка заканчивается одним
completion(...)иreturn, вguardэто легко забыть; - поток: колбэк
URLSessionприходит не на главной очереди, поэтому интерфейс обновляется черезDispatchQueue.main.asyncили@MainActor; - удобства
Result:map,flatMap,mapError,get()для перехода вthrowsи инициализаторResult { try ... }.
В новом коде (с iOS 15) ту же логику чаще пишут через let (data, response) = try await URLSession.shared.data(from: url) и do/catch, а со Swift 6 можно объявить throws(NetworkError) и получить типизированную ошибку без Result. Сам Result остаётся уместным там, где результат нужно сохранить или передать дальше, например в кэш или в состояние экрана. Alamofire отдаёт тот же тип: response.result имеет вид Result<Value, AFError>.
Где спотыкаются
Считают запрос успешным, если error == nil. Сервер вернул 500 с HTML-страницей, и дальше падает декодирование с непонятной ошибкой.
Обновляют UI прямо в колбэке. Main Thread Checker ругается, интерфейс мерцает или падает.
Показывают пользователю error.localizedDescription на любую ошибку, включая отмену. URLError.cancelled и CancellationError при уходе с экрана не повод для алерта.