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 — поддръжка на множество едновременни връзки чрез единична сесия, конфигурируеми настройки и възможност за спиране и възобновяване на изтегляния. Сесия обединява група от мрежови задачи с общи настройки: кеширане, политика за бисквитки, тайм-аути, TLS сертификати.
В iOS URLSession работи със системния DNS кеш, управлението на енергията и фоновите процеси. Когато приложението е минимизирано, системата може да продължи изтеглянето на данни чрез фонова сесия, а след завършване да уведоми приложението чрез handler за завършване. Фоновите сесии са особено полезни за изтегляне на големи файлове, актуализиране на съдържание и синхронизиране на данни в приложения за работа с документи и медийни файлове. За работа с фонови сесии трябва да се имплементира делегат URLSessionDelegate и да се предаде идентификатор на конфигурацията при създаване на сесията — системата използва този идентификатор за възстановяване на сесията след рестартиране на приложението.
Важно предимство на URLSession е поддръжката на HTTP/2 и HTTP/3. Мултиплексирането на HTTP/2 позволява изпращане на множество заявки чрез една TCP връзка, което намалява забавянето и натоварването на сървъра. HTTP/3, базиран на протокола QUIC върху UDP, осигурява още по-бързо установяване на връзка чрез елиминиране на TCP ръкостискането.
Архитектурата на URLSession се състои от три ключови компонента: конфигурация на сесията, самата сесия и задачи (tasks). Всеки компонент отговаря за свой аспект на мрежовото взаимодействие и комбинацията им определя поведението на приложението при работа с мрежата.
Конфигурацията задава параметрите на сесията — от тайм-аути до политики за кеширане. Съществуват три типа: .default (стандартна с дисков кеш), .ephemeral (без запазване на кеш и бисквитки) и .background (за фоново изтегляне). В конфигурацията могат да се зададат максимален брой връзки на хост, тайм-аут на заявка и ресурс, TLS политика и прокси.
URLSessionTask — базов клас за всички мрежови операции. Основните подкласове: URLSessionDataTask за GET и POST заявки с връщане на данни в паметта, URLSessionDownloadTask за изтегляне на файлове на диска, URLSessionUploadTask за изпращане на файлове към сървъра и URLSessionWebSocketTask за работа с WebSocket от iOS 13.
Делегатът на сесията получава събития за напредъка на задачите: получаване на данни, завършване на изтегляне, грешки при удостоверяване, пренасочвания. URLSessionDelegate и неговите подпротоколи позволяват прихващане на TLS сертификати при удостоверяване, управление на кеширане на отговори чрез URLCache и наблюдение на напредъка при изтегляне на големи файлове. Алтернативно, могат да се използват closures (completion handlers) в прости случаи, когато не се изисква обработка на междинни събития.
Основният сценарий за работа с URLSession изглежда така: създава се конфигурация, на нейна основа — сесия, след това чрез сесията се създава задача с URL заявка и задачата се стартира. Нека разгледаме пример за GET заявка с closure. Този модел се използва в повечето 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(). Closure се изпълнява след завършване на заявката и връща data, response или error. За персонализирана сесия със собствена конфигурация използвайте инициализатора URLSession(configuration:), който позволява задаване на политики за кеширане, тайм-аути, максимален брой връзки, подразбиращи се HTTP заглавки и прокси настройки за всички задачи на сесията. Този подход предоставя пълен контрол върху мрежовото поведение в приложението.
URLSession поддържа изтегляне на файлове с възможност за спиране и възобновяване, както и фоново изтегляне. DownloadTask записва файла в временна директория, а в closure за завършване трябва да се премести на постоянно място.
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 в closure указва временния файл, който трябва да се премести, в противен случай системата ще го изтрие след излизане от closure. За проследяване на напредъка се използва делегат URLSessionDownloadDelegate с метода didWriteData, който предава броя записани байтове и общия размер на файла — тези данни могат да се използват за показване на лента за напредък в потребителския интерфейс. Фоновите сесии с downloadTask позволяват продължаване на изтеглянето дори след минимизиране на приложението, а след завършване системата извиква handler в AppDelegate.
Alamofire — е Swift библиотека, изградена върху URLSession, която предоставя по-декларативен интерфейс. Изборът между родния API и Alamofire зависи от сложността на проекта и предпочитанията на екипа.
| Критерий | URLSession | Alamofire |
|---|---|---|
| Зависимости | Няма, вграден във Foundation | Изисква SPM или CocoaPods |
| Синтаксис | Императивен с closures | Декларативен с вериги |
| Обработка на JSON | JSONSerialization ръчно | responseDecodable с Codable |
| Прихващачи | Чрез делегати | RequestInterceptor, EventMonitor |
| Напредък | Чрез делегат | downloadProgress, uploadProgress |
За прости проекти URLSession е достатъчен и не добавя зависимости. Alamofire е оправдан в проекти с множество мрежови заявки, сложна обработка на грешки и изискване за кратък синтаксис. И двете технологии използват общата основа URLSessionConfiguration и са съвместими помежду си. При избора трябва да се вземе предвид, че URLSession се контролира изцяло от Apple и се актуализира заедно с iOS, докато Alamofire изисква поддръжка на съвместимост с нови версии на ОС от страна на разработчиците на библиотеката.
Модерният Swift поддържа async/await, който прави мрежовите заявки по-четими в сравнение с closures. Нека разгледаме същата 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:). Приложението регистрира handler за завършване в AppDelegate и получава резултати дори след минимизиране или затваряне. Системата управлява изтеглянето и уведомява приложението чрез делегата sessionDidFinishEvents.
Да, от iOS 13 URLSession поддържа WebSocket чрез класа URLSessionWebSocketTask. Създава се чрез метода webSocketTask(with:) и предоставя методи send, receive с поддръжка на текстови и двоични съобщения, както и ping/pong за поддържане на връзката.
Тайм-аутите се настройват чрез URLSessionConfiguration: свойствата timeoutIntervalForRequest (изчакване на отговор на заявка) и timeoutIntervalForResource (максимално време за цялото изтегляне). По подразбиране: 60 секунди за заявка и 7 дни за ресурс.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също