Background Task: kluczowe pojęcia, rejestracja zadań i wykonywanie w tle

Autor: IT Sectr Opublikowano: 2026-03-27 Czas czytania: 10 min

Background Task — mechanizm iOS, który pozwala aplikacji dokończyć rozpoczętą operację po przejściu w tryb tła. System przydziela ograniczony czas (do 30 sekund) na wykonanie zadania, po czym aplikacja jest przymusowo wstrzymywana. Według Apple, 2026, użycie expiration handler jest obowiązkowym wymogiem poprawnego zakończenia zadania w tle.

Najważniejsze

  • Background Task — mechanizm iOS do kończenia operacji po przejściu aplikacji w tło.
  • beginBackgroundTask — kluczowa metoda UIApplication do rejestracji zadania w tle.
  • Expiration handler — blok kodu wywoływany przez system po wyczerpaniu przydzielonego czasu.
  • Ograniczenie 30 sekund — standardowy czas wykonania, przedłużenie przez Background Modes.
  • UIApplication.shared.endBackgroundTask — obowiązkowe wywołanie do poprawnego zakończenia zadania.

Czym jest Background Task w iOS?

Background Task — to programowy mechanizm iOS, pozwalający aplikacji wydłużyć czas wykonywania po przejściu w tryb tła. Gdy użytkownik minimalizuje aplikację, system wywołuje UIApplicationDelegate.applicationDidEnterBackground. Jeśli w tym momencie wykonywana jest krytyczna operacja (zapisywanie danych, wysyłanie żądania), aplikacja może poprosić o dodatkowy czas przez beginBackgroundTask.

Po co są Background Tasks

Bez użycia Background Task aplikacja jest przymusowo wstrzymywana po 3–5 sekundach od przejścia w tło. Wszystkie niezakończone operacje są przerywane: dane nie są zapisywane, żądania sieciowe są urywane, stany są tracone. Background Task daje aplikacji do 30 sekund na poprawne dokończenie tych operacji.

  • Zapisywanie stanu — zapis danych w CoreData, UserDefaults lub systemie plików.
  • Kończenie żądań sieciowych — oczekiwanie na odpowiedź z serwera i przetworzenie wyniku.
  • Wysyłanie analityki — przekazywanie zdarzeń na serwer analityczny przed wstrzymaniem.
  • Czyszczenie zasobów — zamykanie deskryptorów plików, zwalnianie pamięci.
  • Buforowanie — zapisywanie pośrednich wyników do przywrócenia przy następnym uruchomieniu.

Historia i ewolucja

beginBackgroundTask pojawił się w iOS 4.0 — pierwszej wersji obsługującej wielozadaniowość. Przed iOS 4 aplikacja była całkowicie zamykana po naciśnięciu przycisku Home. Od iOS 7 pojawiły się Background Fetch i URLSession background configuration. Począwszy od iOS 13, Apple zaleca BGTaskScheduler dla nowych projektów, ale beginBackgroundTask pozostaje aktualny dla krótkoterminowych operacji.

Jak działa beginBackgroundTask: cykl życia

beginBackgroundTask — metoda UIApplication, która rejestruje zadanie i zwraca unikalny identyfikator UIBackgroundTaskIdentifier. System wydłuża licznik czasu wykonywania w tle. Po upływie czasu wywoływany jest expiration handler, po czym aplikacja musi wywołać endBackgroundTask(identifier:) dla poprawnego zakończenia.

Proces krok po kroku

Krok 1 — aplikacja otrzymuje powiadomienie didEnterBackground. Krok 2 — wywoływane jest beginBackgroundTask(expirationHandler:). Krok 3 — wykonywana jest krytyczna operacja (zapisywanie, żądanie sieciowe). Krok 4 — po zakończeniu wywoływane jest endBackgroundTask(identifier:). Jeśli operacja nie zakończy się w ciągu 30 sekund — system wywołuje expiration handler, a aplikacja musi natychmiast zakończyć zadanie.

swift
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

func startBackgroundTask() {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Expiration handler
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

func finishBackgroundTask() {
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

UIApplication.shared.backgroundTimeRemaining

Właściwość backgroundTimeRemaining zwraca liczbę sekund pozostałych do przymusowego zakończenia zadania w tle. Wartość zmniejsza się w czasie rzeczywistym. Jeśli aplikacja nie jest w tle — zwraca DBL_MAX. Użyj tej właściwości do dostosowania zachowania: gdy pozostało mniej niż 5 sekund, przerywaj długotrwałe operacje i zapisuj postęp.

Wiele zadań

Aplikacja może zarejestrować kilka Background Task jednocześnie. Każde zadanie otrzymuje własny identyfikator. Łączny czas wykonywania sumuje się — jeśli zarejestrowano 3 zadania, aplikacja może otrzymać do 90 sekund. Jednak system może zakończyć aplikację wcześniej, jeśli zasoby są wyczerpane lub przekroczono limit baterii.

Expiration handler: obowiązkowa obsługa zakończenia

Expiration handler — to blok kodu wywoływany przez system po wyczerpaniu przydzielonego czasu na zadanie w tle. Obecność expiration handler jest obowiązkowym wymogiem Apple. Bez niego aplikacja może zostać przymusowo zakończona przez system, a dane mogą zostać utracone.

Co powinno znaleźć się w expiration handler

Expiration handler powinien wykonać minimalne działania w celu zapisania stanu aplikacji: zapisać bieżące dane w trwałym magazynie, wywołać endBackgroundTask z odpowiednim identyfikatorem i ustawić identyfikator na .invalid. Wewnątrz expiration handler zabronione jest uruchamianie nowych długotrwałych operacji — czas wykonania jest ograniczony do 1–2 sekund.

swift
func handleExpiration() {
    // Zapisujemy postęp wykonania
    saveProgressToUserDefaults()

    // Anulujemy aktywne żądania sieciowe
    currentTask?.cancel()

    // Kończymy Background Task
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

// Rejestracja z expiration handler
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
    withName: "SaveDocument",
    expirationHandler: handleExpiration
)

Błędy podczas pracy z expiration handler

Najczęstszym błędem jest niewywołanie endBackgroundTask wewnątrz expiration handler. W takim przypadku system nadal uważa zadanie za aktywne, aplikacja nie przechodzi w stan Suspended, a bateria się rozładowuje. Drugi błąd to uruchamianie długotrwałych operacji wewnątrz expiration handler. System może zakończyć aplikację przed ich ukończeniem, a dane zostaną utracone.

Sprawdzanie pozostałego czasu

W expiration handler czas wykonania jest krytycznie krótki — zazwyczaj mniej niż 1 sekunda. Dlatego wewnątrz handler nie można wykonywać: złożonych obliczeń, żądań sieciowych, zapisu dużych ilości danych w CoreData. Tylko atomowe operacje: zapis jednego klucza w UserDefaults, ustawienie flagi stanu, wywołanie endBackgroundTask.

Przykłady kodu Background Task w Swift

Rozważmy pełną implementację Background Task do zapisu dokumentu podczas przejścia aplikacji w tło. Przykład obejmuje rejestrację zadania, wykonanie operacji z kontrolą pozostałego czasu i poprawne zakończenie przez endBackgroundTask.

Zapisywanie dokumentu z postępem

Podczas przejścia w tło aplikacja inicjuje zapis dużego dokumentu. Background Task daje do 30 sekund na operację. Jeśli czas wygaśnie — expiration handler zapisuje pośrednie wyniki. Po zakończeniu zapisu wywoływane jest endBackgroundTask w celu zwolnienia zasobów.

swift
class DocumentManager {
    private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

    func saveDocumentInBackground(document: Document) {
        backgroundTaskID = UIApplication.shared.beginBackgroundTask {
            self.saveProgress(document)
            self.endBackgroundTask()
        }

        DispatchQueue.global().async {
            document.save()
            self.endBackgroundTask()
        }
    }

    private func endBackgroundTask() {
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

Wysyłanie danych na serwer

Żądania sieciowe w tle wymagają szczególnej uwagi — expiration handler może przerwać żądanie przed otrzymaniem odpowiedzi. Użyj URLSession z dataTask i sprawdzaj backgroundTimeRemaining przed wysłaniem. Jeśli pozostało mniej niż 5 sekund — odłóż wysłanie do następnego przebudzenia aplikacji.

swift
func sendCriticalData(data: Data) {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Zapisujemy dane do ponownego wysłania
        saveForRetry(data)
        self.endBackgroundTask()
    }

    let task = URLSession.shared.dataTask(with: request) { _, _, error in
        if error != nil {
            saveForRetry(data)
        }
        self.endBackgroundTask()
    }
    task.resume()
}

Monitorowanie pozostałego czasu

W przypadku długotrwałych operacji śledź UIApplication.shared.backgroundTimeRemaining. Jeśli wartość spadnie poniżej progu (10 sekund), przerwij bieżącą operację i uruchom zapisywanie pośrednich wyników. Pozwala to poprawnie zakończyć pracę przed przymusowym wywołaniem expiration handler.

Najlepsze praktyki korzystania z Background Task

Background Task — potężny mechanizm, ale jego nieprawidłowe użycie prowadzi do problemów z baterią i wydajnością. Przestrzeganie zaleceń Apple i sprawdzonych praktyk społeczności pomoże uniknąć typowych błędów i zapewnić stabilne działanie aplikacji.

Minimalizacja czasu wykonywania

Kończ Background Task tak szybko, jak to możliwe. Każda sekunda wykonywania w tle zużywa energię baterii. Optymalny czas — poniżej 5 sekund. Jeśli operacja trwa dłużej — rozważ użycie BGTaskScheduler lub Background Modes. Nie przedłużaj zadania sztucznie przez wywołania beginBackgroundTask bez rzeczywistej potrzeby.

Prawidłowe używanie identyfikatorów

Przechowuj UIBackgroundTaskIdentifier jako właściwość klasy lub struktury. Nigdy nie przekazuj go jako zmiennej globalnej — prowadzi to do konfliktów przy wielu zadaniach. Ustawiaj identyfikator na .invalid po wywołaniu endBackgroundTask, aby zapobiec podwójnemu zakończeniu.

Testowanie Background Task

W Xcode Simulator przełącz aplikację w tło przez przycisk Home (Command + Shift + H). Użyj Debug — Simulate Background Fetch do testowania przebudzenia w tle. Aby symulować wygaśnięcie czasu, ustaw zmienną środowiskową BACKGROUND_TASK_SIMULATE_EXPIRATION = YES — expiration handler zostanie wywołany po 5 sekundach.

swift
// Sprawdzenie pozostałego czasu przed rozpoczęciem operacji
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
    // Niewystarczająco czasu — odłóż zadanie
    scheduleForNextLaunch()
    return
}

// Wykonanie operacji z kontrolą czasu
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
    saveProgress()
    self.endBackgroundTask()
}

Unikaj retain cycles

Expiration handler przechwytuje self — może to utworzyć retain cycle, jeśli backgroundTaskID jest przechowywany jako właściwość tego samego obiektu. Użyj [weak self] w domknięciu lub przechowuj identyfikator osobno. Retain cycle prowadzi do wycieku pamięci — obiekt nie zostanie zwolniony do czasu zakończenia aplikacji.

Background Task vs BGTaskScheduler: porównanie podejść

Wraz z wydaniem iOS 13 Apple przedstawiło BGTaskScheduler — nowoczesny zamiennik starego API Background Task. Oba mechanizmy rozwiązują podobne zadania, ale BGTaskScheduler zapewnia większą kontrolę i elastyczność. Zrozumienie różnic pomoże wybrać odpowiednie narzędzie dla konkretnego scenariusza.

CechaBackground TaskBGTaskScheduler
Wersja iOS4.0+13.0+
Maks. czas30 sekund30 s / 10 min (processing)
InicjacjadidEnterBackgroundPlanowanie + system
Gwarancja wykonaniaTylko przy przejściu w tłoW dowolnym dogodnym dla systemu czasie
Expiration handlerTak, obowiązkowyTak, przez task.expirationHandler
InternetWymagany przy uruchomieniuDostępny przez requiresNetworkConnectivity
ŁadowanieNiewymaganeOpcjonalne dla processing

Kiedy używać Background Task

beginBackgroundTask nadaje się do krótkoterminowych operacji, które należy wykonać natychmiast po przejściu w tło: zapis stanu, dokończenie żądania sieciowego, buforowanie danych. API jest proste i nie wymaga konfiguracji Info.plist ani rejestracji identyfikatorów. Idealne dla operacji trwających mniej niż 10 sekund.

Kiedy używać BGTaskScheduler

BGTaskScheduler nadaje się do zadań, które mogą być wykonane w dowolnym dogodnym czasie: okresowa synchronizacja, czyszczenie pamięci podręcznej, aktualizacja widżetów. System sam wybiera optymalny czas, uwzględniając zachowanie użytkownika i stan baterii. W przypadku długotrwałych operacji (do 10 minut) użyj BGProcessingTask.

Wspólne używanie

Oba API można używać w jednej aplikacji. Background Task — do natychmiastowych operacji przy przejściu w tło (zapis szkicu). BGTaskScheduler — do planowanych aktualizacji (synchronizacja co 6 godzin). Podział odpowiedzialności pozwala zagwarantować poprawne zapisywanie danych i energooszczędną obsługę w tle.

Często zadawane pytania

Czy można wywołać beginBackgroundTask nie w didEnterBackground?

Tak, beginBackgroundTask można wywołać w dowolnym momencie działania aplikacji. Jednak systemowe przydzielenie czasu rozpocznie się dopiero po przejściu w tło. Jeśli aplikacja jest na pierwszym planie, wywołanie beginBackgroundTask nie ma efektu — backgroundTimeRemaining zwraca DBL_MAX, a zadanie zostanie aktywowane po przejściu w tło.

Co się stanie, jeśli nie wywołasz endBackgroundTask?

Jeśli nie wywołasz endBackgroundTask, system nadal będzie uważać aplikację za aktywną w tle. Po 30 sekundach zostanie wywołany expiration handler, ale jeśli w nim również nie ma endBackgroundTask — aplikacja pozostanie w pamięci, zużywając baterię. W iOS 13+ system przymusowo zamyka taką aplikację po 3 minutach.

Jak wydłużyć czas Background Task powyżej 30 sekund?

Standardowy czas to 30 sekund. Wydłużyć go można tylko przez Background Modes: Audio (odtwarzanie), Location (geolokalizacja), Bluetooth (BLE). Lub przez BGProcessingTask (iOS 13+) — do 10 minut przy ładowaniu i Wi-Fi. beginBackgroundTask sam w sobie nie zapewnia sposobu na zwiększenie limitu.

Czy Background Task działa na iPadzie?

Tak, iPadOS w pełni obsługuje beginBackgroundTask z tymi samymi ograniczeniami co iOS. Na iPadzie z Stage Manager aplikacja może pozostać w pamięci dłużej — system rzadziej wstrzymuje aplikacje ze względu na większą ilość RAM. Jednak limit 30 sekund na zadanie w tle pozostaje.

Jak debugować Background Task na prawdziwym urządzeniu?

Podłącz urządzenie do Xcode, uruchom aplikację, zminimalizuj ją — w konsoli pojawią się logi systemowe. Użyj sysdiagnose do zebrania szczegółowych logów: wymuś sysdiagnose z urządzenia (Volume Up + Down + Power). W Xcode Debug Navigator śledź aktywność zadań w tle.

Podsumowanie

  • Background Task — mechanizm iOS do kończenia operacji po przejściu w tło, dostępny od iOS 4.0.
  • beginBackgroundTask — metoda UIApplication rejestrująca zadanie i zwracająca identyfikator do jego zakończenia.
  • Expiration handler — obowiązkowy blok kodu wywoływany przez system po wyczerpaniu 30-sekundowego limitu.
  • endBackgroundTask — obowiązkowe wywołanie do poprawnego zakończenia zadania; bez niego aplikacja pozostaje w pamięci.
  • BGTaskScheduler — nowoczesna alternatywa (iOS 13+) z planowaniem, dwoma typami zadań i warunkami wykonania.
  • backgroundTimeRemaining — właściwość do sprawdzania pozostałego czasu i dostosowywania zachowania zadania.
  • Używaj Background Task do natychmiastowych krótkoterminowych operacji i BGTaskScheduler do planowanych aktualizacji w tle w nowych projektach.

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.

Omów projekt

Przeczytaj również