URLSession — to API dla zapytań sieciowych w iOS i macOS, wchodzące w skład Foundation framework i zapewniające jednolity interfejs do pracy z HTTP, HTTPS, pobieraniem w tle i WebSocket. Zastąpił przestarzały NSURLConnection i stał się głównym narzędziem sieciowym dla deweloperów Apple. Według Apple Developer Documentation (2025), URLSession obsługuje ponad 90% ruchu sieciowego w aplikacjach na iPhone i iPad.
Najważniejsze
URLSession — to API do operacji sieciowych, wprowadzone przez Apple w iOS 7 i macOS 10.9. Zastąpił NSURLConnection i zapewnił bardziej elastyczny i wydajny model pracy z siecią. Biblioteka obsługuje HTTP/1.1, HTTP/2, HTTP/3 i WebSocket, a także sesje w tle do pobierania danych.
Główną zaletą URLSession w porównaniu ze starym NSURLConnection jest obsługa wielu równoczesnych połączeń przez jedną sesję, konfigurowalne ustawienia oraz możliwość wstrzymywania i wznawiania pobierania. Sesja grupuje zestaw zadań sieciowych ze wspólnymi ustawieniami: buforowanie, polityka cookie, limity czasu, certyfikaty TLS.
W iOS URLSession współpracuje z systemowym cache DNS, zarządzaniem energią i procesami w tle. Po zminimalizowaniu aplikacji system może kontynuować pobieranie danych przez sesję w tle, a po zakończeniu — powiadomić aplikację przez handler zakończenia. Sesje w tle są szczególnie przydatne do pobierania dużych plików, aktualizacji treści i synchronizacji danych w aplikacjach do pracy z dokumentami i plikami multimedialnymi. Do pracy z sesjami w tle należy zaimplementować delegata URLSessionDelegate i przekazać identyfikator konfiguracji przy tworzeniu sesji — system używa tego identyfikatora do przywrócenia sesji po ponownym uruchomieniu aplikacji.
Ważną zaletą URLSession jest obsługa HTTP/2 i HTTP/3. Multipleksowanie HTTP/2 pozwala wysyłać wiele zapytań przez jedno połączenie TCP, co zmniejsza opóźnienia i obciążenie serwera. HTTP/3, oparty na protokole QUIC działającym na UDP, zapewnia jeszcze szybsze nawiązywanie połączenia dzięki eliminacji uzgadniania TCP.
Architektura URLSession składa się z trzech kluczowych komponentów: konfiguracji sesji, samej sesji i zadań (tasks). Każdy komponent odpowiada za swój aspekt interakcji sieciowej, a ich kombinacja określa zachowanie aplikacji podczas pracy z siecią.
Konfiguracja określa parametry sesji — od limitów czasu po polityki buforowania. Istnieją trzy typy: .default (standardowa z cache dyskowym), .ephemeral (bez zapisywania cache i cookie) oraz .background (do pobierania w tle). W konfiguracji można ustawić maksymalną liczbę połączeń na host, limit czasu zapytania i zasobu, politykę TLS oraz proxy.
URLSessionTask — klasa bazowa dla wszystkich operacji sieciowych. Główne podklasy: URLSessionDataTask dla zapytań GET i POST z zwracaniem danych w pamięci, URLSessionDownloadTask do pobierania plików na dysk, URLSessionUploadTask do wysyłania plików na serwer oraz URLSessionWebSocketTask do pracy z WebSocket od iOS 13.
Delegat sesji otrzymuje zdarzenia dotyczące przebiegu zadań: otrzymywanie danych, zakończenie pobierania, błędy uwierzytelniania, przekierowania. URLSessionDelegate i jego podprotokoły umożliwiają przechwytywanie certyfikatów TLS przy uwierzytelnianiu, zarządzanie buforowaniem odpowiedzi przez URLCache oraz monitorowanie postępu pobierania dużych plików. Alternatywnie można używać domknięć (completion handlers) w prostych przypadkach, gdy nie jest wymagane przetwarzanie zdarzeń pośrednich.
Podstawowy scenariusz pracy z URLSession wygląda następująco: tworzona jest konfiguracja, na jej podstawie — sesja, następnie przez sesję tworzone jest zadanie z zapytaniem URL, a zadanie jest uruchamiane. Omówmy przykład zapytania GET z domknięciem. Ten wzorzec jest używany w większości aplikacji iOS do pobierania danych z REST API, ładowania obrazów i interakcji z usługami chmurowymi.
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("Błąd: \(error!.localizedDescription)")
return
}
if let json = try? JSONSerialization.jsonObject(with: data) {
print("JSON: \(json)")
}
}
task.resume()
W przykładzie użyto URLSession.shared — singletona z konfiguracją .default dla prostych zapytań. dataTask tworzy operację asynchroniczną, ale jej nie uruchamia — konieczne jest wywołanie resume(). Domknięcie wykonuje się po zakończeniu zapytania i zwraca data, response lub error. Dla niestandardowej sesji z własną konfiguracją użyj inicjalizatora URLSession(configuration:), który pozwala ustawić polityki buforowania, limity czasu, maksymalną liczbę połączeń, domyślne nagłówki HTTP oraz ustawienia proxy dla wszystkich zadań sesji. Takie podejście daje pełną kontrolę nad zachowaniem sieci w aplikacji.
URLSession obsługuje pobieranie plików z możliwością wstrzymywania i wznawiania, a także pobieranie w tle. DownloadTask zapisuje plik do tymczasowego katalogu, a w domknięciu completion należy przenieść go do stałej lokalizacji.
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()
Parametr location w domknięciu wskazuje na plik tymczasowy, który należy przenieść, w przeciwnym razie system usunie go po wyjściu z domknięcia. Do śledzenia postępu używany jest delegat URLSessionDownloadDelegate z metodą didWriteData, która przekazuje liczbę zapisanych bajtów i całkowity rozmiar pliku — te dane można wykorzystać do wyświetlania paska postępu w interfejsie użytkownika. Sesje w tle z downloadTask umożliwiają kontynuowanie pobierania nawet po zminimalizowaniu aplikacji, a po zakończeniu system wywołuje handler w AppDelegate.
Alamofire — to biblioteka Swift zbudowana na bazie URLSession, zapewniająca bardziej deklaratywny interfejs. Wybór między natywnym API a Alamofire zależy od złożoności projektu i preferencji zespołu.
| Kryterium | URLSession | Alamofire |
|---|---|---|
| Zależności | Brak, wbudowany w Foundation | Wymaga SPM lub CocoaPods |
| Składnia | Imperatywna z domknięciami | Deklaratywna z łańcuchami |
| Obsługa JSON | JSONSerialization ręcznie | responseDecodable z Codable |
| Przechwytywacze | Przez delegaty | RequestInterceptor, EventMonitor |
| Postęp | Przez delegata | downloadProgress, uploadProgress |
Dla prostych projektów URLSession jest wystarczający i nie dodaje zależności. Alamofire jest uzasadniony w projektach z wieloma zapytaniami sieciowymi, złożoną obsługą błędów i wymaganiem zwięzłej składni. Obie technologie korzystają ze wspólnego fundamentu URLSessionConfiguration i są ze sobą kompatybilne. Przy wyborze warto wziąć pod uwagę, że URLSession jest w pełni kontrolowany przez Apple i aktualizowany wraz z iOS, podczas gdy Alamofire wymaga od twórców biblioteki wsparcia kompatybilności z nowymi wersjami systemu operacyjnego.
Nowoczesny Swift obsługuje async/await, który sprawia, że zapytania sieciowe są bardziej czytelne w porównaniu z domknięciami. Rozważmy to samo zapytanie GET z użyciem składni asynchronicznej.
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
}
Metoda data(from:) jest dostępna od iOS 15 i macOS 12. Zwraca krotkę (Data, URLResponse) i zgłasza błąd w przypadku problemów z siecią. JSONDecoder z modelem Codable automatycznie deserializuje odpowiedź — zastępuje to rozwlekły JSONSerialization z poprzedniego przykładu.
Dla zapytań POST z ciałem JSON używany jest URLRequest, w którym konfiguruje się metodę, nagłówki Content-Type oraz ciało zapytania w formacie Data. Async/await czyni ten proces zwięzłym i przejrzystym, a obsługa błędów jest prosta dzięki blokowi 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)
}
Często zadawane pytania
URLSession to nowoczesny zamiennik NSURLConnection, wprowadzony w iOS 7. Główne różnice: obsługa wielu połączeń przez sesje, wstrzymywanie i wznawianie zadań, pobieranie w tle oraz WebSocket. NSURLConnection jest przestarzały i nie zaleca się jego używania w nowych projektach.
Do śledzenia postępu używany jest delegat URLSessionDownloadDelegate z metodą urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite). Alternatywnie dla dataTask można zasubskrybować URLSessionTaskDelegate i otrzymywać aktualizacje przez didSendBodyData.
Pobieranie w tle konfiguruje się przez ustawienie .background(withIdentifier:). Aplikacja rejestruje handler zakończenia w AppDelegate i otrzymuje wyniki nawet po zminimalizowaniu lub zamknięciu. System zarządza pobieraniem i powiadamia aplikację przez delegata sessionDidFinishEvents.
Tak, od iOS 13 URLSession obsługuje WebSocket przez klasę URLSessionWebSocketTask. Jest tworzona metodą webSocketTask(with:) i udostępnia metody send, receive z obsługą wiadomości tekstowych i binarnych, a także ping/pong do utrzymywania połączenia.
Limity czasu konfiguruje się przez URLSessionConfiguration: właściwości timeoutIntervalForRequest (oczekiwanie na odpowiedź) i timeoutIntervalForResource (maksymalny czas całego pobierania). Domyślnie: 60 sekund dla zapytania i 7 dni dla zasobu.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również