URLSession — это API для сетевых запросов в iOS и macOS, входящий в Foundation framework и предоставляющий единый интерфейс для работы с HTTP, HTTPS, фоновой загрузки и WebSocket. Он заменил устаревший NSURLConnection и стал основным сетевым инструментом для разработчиков Apple. По данным Apple Developer Documentation (2025), URLSession обрабатывает более 90% сетевого трафика в приложениях для iPhone и iPad.
Главное
URLSession — это API для сетевых операций, представленный Apple в iOS 7 и macOS 10.9. Он заменил NSURLConnection и предоставил более гибкую и мощную модель для работы с сетью. Библиотека поддерживает HTTP/1.1, HTTP/2, HTTP/3 и WebSocket, а также фоновые сессии для загрузки данных.
Основное преимущество URLSession перед старым NSURLConnection — поддержка множества одновременных соединений через единую сессию, настраиваемые конфигурации и возможность приостанавливать и возобновлять загрузки. Сессия объединяет группу сетевых задач с общими настройками: кэширование, политика cookie, тайм-ауты, сертификаты TLS.
В iOS URLSession работает с системным DNS-кешем, управлением питанием и фоновыми процессами. При свёрнутом приложении система может продолжать загрузку данных через фоновую сессию, а после завершения — уведомить приложение через обработчик завершения. Фоновые сессии особенно полезны для загрузки больших файлов, обновления контента и синхронизации данных в приложениях для работы с документами и медиафайлами. Для работы с фоновыми сессиями необходимо реализовать делегат URLSessionDelegate и передать идентификатор конфигурации при создании сессии — система использует этот идентификатор для восстановления сессии после перезапуска приложения.
Важное преимущество URLSession — поддержка HTTP/2 и HTTP/3. Мультиплексирование HTTP/2 позволяет отправлять несколько запросов через одно TCP-соединение, что снижает задержки и нагрузку на сервер. HTTP/3, основанный на протоколе QUIC поверх UDP, обеспечивает ещё более быстрое установление соединения за счёт устранения TCP-рукопожатия.
Архитектура URLSession состоит из трёх ключевых компонентов: конфигурация сессии, сама сессия и задачи (tasks). Каждый компонент отвечает за свой аспект сетевого взаимодействия, и их комбинация определяет поведение приложения при работе с сетью.
Конфигурация задаёт параметры сессии — от тайм-аутов до политик кэширования. Существует три типа: .default (стандартная с дисковым кэшем), .ephemeral (без сохранения кэша и cookie) и .background (для фоновой загрузки). В конфигурации можно задать максимальное количество соединений на хост, тайм-аут запроса и ресурса, политику TLS и прокси.
URLSessionTask — базовый класс для всех сетевых операций. Основные подклассы: URLSessionDataTask для GET и POST запросов с возвратом данных в памяти, URLSessionDownloadTask для скачивания файлов на диск, URLSessionUploadTask для отправки файлов на сервер и URLSessionWebSocketTask для работы с WebSocket с iOS 13.
Делегат сессии получает события о ходе выполнения задач: получение данных, завершение загрузки, ошибки аутентификации, редиректы. URLSessionDelegate и его подпротоколы позволяют перехватывать сертификаты TLS при аутентификации, управлять кэшированием ответов через URLCache и мониторить прогресс загрузки крупных файлов. Альтернативно можно использовать замыкания (completion handlers) для простых случаев, когда не требуется обработка промежуточных событий.
Базовый сценарий работы с URLSession выглядит так: создаётся конфигурация, на её основе — сессия, затем через сессию создаётся задача с URL-запросом, и задача запускается. Разберём пример GET-запроса с замыканием. Этот паттерн используется в большинстве iOS-приложений для получения данных от REST API, загрузки изображений и взаимодействия с облачными сервисами.
let url = URL(string: "https://api.example.com/users")!
let session = URLSession.shared
let task = session.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
print("Ошибка: \(error!.localizedDescription)")
return
}
if let json = try? JSONSerialization.jsonObject(with: data) {
print("JSON: \(json)")
}
}
task.resume()
В примере используется URLSession.shared — синглтон с конфигурацией .default для простых запросов. dataTask создаёт асинхронную операцию, но не запускает её — обязательно вызывать resume(). Замыкание срабатывает после завершения запроса и возвращает data, response или error. Для кастомной сессии с собственной конфигурацией используйте инициализатор URLSession(configuration:), который позволяет задать политики кэширования, тайм-ауты, максимальное количество соединений, HTTP-заголовки по умолчанию и настройки прокси для всех задач сессии. Такой подход даёт полный контроль над поведением сети в приложении.
URLSession поддерживает загрузку файлов с возможностью приостановки и возобновления, а также фоновую загрузку. DownloadTask сохраняет файл во временную директорию, а в замыкании completion нужно переместить его в постоянное место.
let url = URL(string: "https://example.com/file.zip")!
let session = URLSession(configuration: .default)
let task = session.downloadTask(with: url) { location, _, _ in
guard let location = location else { return }
let destination = FileManager.default.temporaryDirectory
.appendingPathComponent("file.zip")
try? FileManager.default.moveItem(at: location, to: destination)
}
task.resume()
Параметр location в замыкании указывает на временный файл, который нужно переместить, иначе система удалит его после выхода из замыкания. Для отслеживания прогресса используется делегат URLSessionDownloadDelegate с методом didWriteData, который передаёт количество записанных байт и общий размер файла — эти данные можно использовать для отображения прогресс-бара в интерфейсе пользователя. Фоновые сессии с downloadTask позволяют продолжать загрузку даже после сворачивания приложения, а при завершении система вызывает обработчик в AppDelegate.
Alamofire — это Swift-библиотека, построенная поверх URLSession и предоставляющая более декларативный интерфейс. Выбор между нативным API и Alamofire зависит от сложности проекта и предпочтений команды.
| Критерий | URLSession | Alamofire |
|---|---|---|
| Зависимости | Нет, встроен в Foundation | Требует SPM или CocoaPods |
| Синтаксис | Императивный с замыканиями | Декларативный с цепочками |
| Обработка JSON | JSONSerialization вручную | responseDecodable с Codable |
| Перехватчики | Через делегаты | RequestInterceptor, EventMonitor |
| Прогресс | Через делегат | downloadProgress, uploadProgress |
Для простых проектов URLSession достаточен и не добавляет зависимостей. Alamofire оправдан в проектах с множеством сетевых запросов, сложной обработкой ошибок и требованием лаконичного синтаксиса. Обе технологии используют общий фундамент URLSessionConfiguration и совместимы друг с другом. При выборе стоит учитывать, что URLSession полностью контролируется Apple и обновляется вместе с iOS, в то время как Alamofire требует поддержки совместимости с новыми версиями ОС со стороны разработчиков библиотеки.
Современный Swift поддерживает async/await, который делает сетевые запросы более читаемыми по сравнению с замыканиями. Рассмотрим тот же GET-запрос с использованием асинхронного синтаксиса.
func fetchUsers() async throws -> [User] {
let url = URL(string: "https://api.example.com/users")!
let (data, _) = try await URLSession.shared.data(from: url)
let users = try JSONDecoder().decode([User].self, from: data)
return users
}
Метод data(from:) доступен с iOS 15 и macOS 12. Он возвращает кортеж (Data, URLResponse) и выбрасывает ошибку при проблемах сети. JSONDecoder с Codable-моделью автоматически десериализует ответ — это заменяет громоздкий JSONSerialization из предыдущего примера.
Для POST-запросов с JSON-телом используется URLRequest, в котором настраиваются метод, заголовки Content-Type и тело запроса в виде Data. Async/await делает этот процесс лаконичным и понятным, а обработка ошибок — простой через do-catch блок.
func createUser(name: String) async throws -> User {
var request = URLRequest(url: URL(string: "https://api.example.com/users")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body = try JSONEncoder().encode(["name": name])
request.httpBody = body
let (data, _) = try await URLSession.shared.data(for: request)
return try JSONDecoder().decode(User.self, from: data)
}
Часто задаваемые вопросы
URLSession — современная замена NSURLConnection, представленная в iOS 7. Основные отличия: поддержка множественных соединений через сессии, приостановка и возобновление задач, фоновая загрузка и WebSocket. NSURLConnection устарел и не рекомендуется к использованию в новых проектах.
Для отслеживания прогресса используется делегат URLSessionDownloadDelegate с методом urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite). Альтернативно для dataTask можно подписаться на URLSessionTaskDelegate и получать обновления через didSendBodyData.
Фоновая загрузка настраивается через конфигурацию .background(withIdentifier:). Приложение регистрирует обработчик завершения в AppDelegate и получает результаты даже после сворачивания или закрытия. Система управляет загрузкой и уведомляет приложение через делегат sessionDidFinishEvents.
Да, с iOS 13 URLSession поддерживает WebSocket через класс URLSessionWebSocketTask. Он создаётся методом webSocketTask(with:) и предоставляет методы send, receive с поддержкой текстовых и бинарных сообщений, а также ping/pong для поддержания соединения.
Тайм-ауты настраиваются через URLSessionConfiguration: свойства timeoutIntervalForRequest (ожидание ответа на запрос) и timeoutIntervalForResource (максимальное время всей загрузки). По умолчанию: 60 секунд для запроса и 7 дней для ресурса.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также