BGTaskScheduler — to framework Apple do planowania i wykonywania zadań w tle w aplikacjach iOS 13 i nowszych. Zastąpił przestarzałe Background Fetch i performFetch, zapewniając jednolite API do pracy z operacjami w tle. Według Apple Developer Documentation, 2026, framework obejmuje dwa typy zadań: BGProcessingTask dla długotrwałych operacji i BGAppRefreshTask dla krótkich aktualizacji treści.
Najważniejsze
BGTaskScheduler — to systemowy framework Apple, wprowadzony w iOS 13, który centralnie zarządza wykonywaniem zadań w tle. Przed jego pojawieniem się programiści używali UIApplication backgroundTasks, performFetch i obsługi zdarzeń w appDelegate, co prowadziło do fragmentacji kodu i nieprzewidywalnego zachowania.
Framework działa na zasadzie planowania z opóźnieniem: aplikacja rejestruje zadania z unikalnymi identyfikatorami, a iOS sam określa optymalny moment ich wykonania. System uwzględnia poziom naładowania baterii, aktywność użytkownika, stan sieci i inne czynniki.
Główne możliwości obejmują pracę zarówno z krótkimi, jak i długotrwałymi operacjami w tle. W przeciwieństwie do AlarmManager w Androidzie, BGTaskScheduler nie gwarantuje dokładnego czasu wykonania — system zastrzega sobie prawo do opóźnienia zadania, jeśli warunki są niekorzystne.
BGTaskScheduler używa architektury opartej na handlerach. Aplikacja rejestruje handler dla każdego typu zadania, a system wywołuje go, gdy nadchodzi odpowiedni moment. Sam framework nie wykonuje zadania bezpośrednio — jedynie powiadamia aplikację, że nadszedł czas, aby je uruchomić.
Rejestracja rozpoczyna się od zadeklarowania identyfikatora zadania w Info.plist przez tablicę BGTaskSchedulerPermittedIdentifiers. Następnie w kodzie aplikacji wywoływana jest metoda registerHandler(forTaskWithIdentifier:) z closurem-handlerem.
import BackgroundTasks
let taskID = "com.example.app.refresh"
BGTaskScheduler.shared.registerHandler(
forTaskWithIdentifier: taskID,
using: DispatchQueue.global()
) { task in
task.expirationHandler = {
// wywoływane przy wymuszonym zakończeniu
}
processBackgroundTask(task as! BGAppRefreshTask)
}
Po rejestracji aplikacja musi jawnie zażądać wykonania zadania przez submitTaskRequest. Żądanie zawiera identyfikator zadania i datę najwcześniejszego możliwego uruchomienia. System zapisuje żądanie i przetwarza je, gdy uzna warunki za odpowiednie.
let request = BGAppRefreshTaskRequest(
identifier: taskID
)
request.earliestBeginDate = Date(timeIntervalSinceNow: 3600)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Błąd planowania: \(error)")
}
BGTaskScheduler zapewnia dwa główne typy zadań, z których każdy jest przeznaczony do własnego scenariusza użycia. Wybór odpowiedniego typu bezpośrednio wpływa na prawdopodobieństwo pomyślnego wykonania zadania przez system.
BGAppRefreshTask jest przeznaczona do krótkich aktualizacji treści w tle: pobieranie nowych danych, synchronizacja z serwerem, aktualizacja widgetów. Czas wykonania jest ograniczony do 30 sekund, po upływie których system wymusza zakończenie zadania. Ten typ zadań jest wykonywany częściej niż BGProcessingTask i ma wyższy priorytet.
BGProcessingTask jest przeznaczona do dłuższych operacji: przetwarzanie plików multimedialnych, indeksowanie danych Core Data, tworzenie kopii zapasowych. Zadanie może trwać do kilku minut, ale system uruchamia je rzadziej i tylko w sprzyjających warunkach — przy podłączeniu do zasilania, stabilnym Wi-Fi i niskim obciążeniu urządzenia.
| Parametr | BGAppRefreshTask | BGProcessingTask |
|---|---|---|
| Limit czasu | 30 sekund | kilka minut |
| Częstotliwość uruchamiania | wysoka | niska |
| Warunki | dowolne | zasilanie + Wi-Fi |
| Wymaga zasilania | nie | zalecane |
| Przykład | aktualizacja kanału | przetwarzanie wideo |
Prawidłowa rejestracja — to obowiązkowy warunek działania BGTaskScheduler. Jeśli zadanie nie jest zarejestrowane w Info.plist, system zignoruje każde żądanie jego wykonania.
Do pliku Info.plist dodaje się tablicę BGTaskSchedulerPermittedIdentifiers z listą identyfikatorów tekstowych. Każdy identyfikator musi być unikalny w ramach aplikacji. Apple zaleca używanie odwrotnej notacji domeny.
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.example.app.refresh</string>
<string>com.example.app.processing</string>
</array>
Do planowania używa się metody submitTaskRequest. Jeśli zadanie nie jest już potrzebne, można je anulować przez cancelTaskRequest lub cancelAllTaskRequests. System automatycznie anuluje zadania przy usunięciu aplikacji lub resecie danych.
BGTaskScheduler umożliwia śledzenie stanu zaplanowanych zadań przez getPendingTaskRequests. Ta metoda zwraca listę wszystkich aktywnych żądań z informacją o ich typie, identyfikatorze i earliestBeginDate. Dla każdego żądania można sprawdzić, czy zostało już wykonane lub anulowane, i podjąć decyzję o ponownym zaplanowaniu.
Ważne, aby pamiętać, że system nie zapewnia bezpośredniego Callback o pomyślności wykonania zadania w tle — handler sam musi zgłosić wynik przez właściwości task. setTaskCompleted pozwala oznaczyć zadanie jako pomyślnie zakończone, po czym system może uruchomić kolejne zaplanowane zadanie tego typu. Jeśli zadanie nie wywoła setTaskCompleted, system uznaje je za zakończone po upływie czasu lub przy wymuszonym zakończeniu.
Do diagnostyki problemów zaleca się używanie OSLog w handlerze i przeglądanie logów przez Console.app na Macu. Apple udostępnia również narzędzie MetricKit do analizy wydajności zadań w tle — zbiera ono dane o czasie wykonania, zużyciu energii i częstotliwości uruchamiania, które można wykorzystać do optymalizacji.
// Anulowanie konkretnego zadania
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: taskID)
// Anulowanie wszystkich zadań
BGTaskScheduler.shared.cancelAllTaskRequests()
// Sprawdzanie zaplanowanych zadań
BGTaskScheduler.shared.getPendingTaskRequests { requests in
print("Zaplanowano \(requests.count) zadań")
}
BGTaskScheduler nakłada ścisłe ograniczenia na pracę w tle. System może opóźnić zadanie na nieokreślony czas, jeśli warunki są niekorzystne. Programista musi rozumieć, że framework nie jest przeznaczony do zadań czasu rzeczywistego.
Wśród kluczowych ograniczeń: system nie gwarantuje wykonania zadania w określonym czasie, maksymalna liczba jednoczesnych zadań jest ograniczona, a zużycie energii jest ściśle kontrolowane. Uruchomienie kilku zadań po sobie może prowadzić do ich połączenia lub anulowania.
Aby zwiększyć prawdopodobieństwo wykonania, zaleca się ustawienie earliestBeginDate nie wcześniej niż za 1 godzinę dla BGProcessingTask i 15 minut dla BGAppRefreshTask. Ważne jest również obsłużenie expirationHandler — jeśli zadanie nie mieści się w limicie, system wywołuje ten handler w celu prawidłowego zakończenia. Ponowne planowanie powinno odbywać się wewnątrz samego handlera, aby utrzymać ciągły cykl pracy w tle.
Kolejne ważne ograniczenie dotyczy żądań sieciowych. BGTaskScheduler nie gwarantuje aktywnego połączenia sieciowego podczas wykonywania zadania. Aplikacja musi samodzielnie sprawdzać dostępność sieci przez NWPathMonitor i odkładać przetwarzanie, jeśli połączenie jest nieobecne. Różni się to od Android JobScheduler, który potrafi aktywować zadanie tylko przy połączeniu z siecią określonego typu. W praktyce programiści często łączą BGTaskScheduler z sesjami URL w tle NSURLSession w celu niezawodnego pobierania danych.
Począwszy od macOS Catalina BGTaskScheduler jest również dostępny na Macu. Pozwala to tworzyć wieloplatformowe zadania w tle dla aplikacji UIKit uruchamianych na Apple Silicon. Na watchOS framework działa w ograniczonym zakresie — dostępne są tylko krótkie BGAppRefreshTask do aktualizacji komplikacji i synchronizacji danych z iPhonem. Programiści powinni uwzględniać różnice platformowe przy planowaniu architektury tła.
Do debugowania BGTaskScheduler Apple udostępnia kilka narzędzi. Polecenie e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.example.task"] w lldb wymusza uruchomienie zadania w tle, ignorując ograniczenia systemowe. W Xcode dostępna jest flaga Symuluj Background Fetch w menu Debug, która emuluje krótką aktualizację w tle. Do analizy wydajności używa się MetricKit — zbiera on informacje o częstotliwości uruchamiania, czasie trwania i zużyciu energii każdego zadania. Te dane pomagają zoptymalizować częstotliwość planowania i wybrać odpowiedni typ zadania.
W praktyce BGTaskScheduler dobrze nadaje się do aktualizacji danych widgetów, synchronizacji iCloud, przetwarzania powiadomień push z treścią i indeksowania wyszukiwania Spotlight. Nie nadaje się do wysyłania analityki w czasie rzeczywistym, aplikacji czatowych ani żadnych zadań wymagających natychmiastowego wykonania.
W celu pogłębionej nauki BGTaskScheduler Apple zaleca oficjalną dokumentację WWDC: sesja „Advances in Background Tasks” (2020) obejmuje migrację z przestarzałych API, a „Background Tasks in Practice” (2021) zawiera rzeczywiste przypadki użycia. Przydatny jest również rozdział Energy Efficiency Guide, w którym opisano, jak framework wpisuje się w ogólną strategię oszczędzania energii Apple. Przykłady kodu są dostępne w oficjalnym repozytorium Apple Developer na GitHub z pełnymi projektami dla iOS i macOS.
Często zadawane pytania
Background Fetch był ograniczony do jednego zadania w tle na aplikację i nie miał mechanizmu priorytetów. BGTaskScheduler obsługuje wiele zadań różnych typów, zapewnia jednolite API i automatyczne zarządzanie energią.
Apple nie ustala wyraźnego ograniczenia liczby zarejestrowanych identyfikatorów, ale w praktyce zaleca się używanie nie więcej niż 5–10 zadań. Większa liczba zmniejsza prawdopodobieństwo wykonania każdego konkretnego zadania z powodu konkurencji o zasoby systemowe.
Do debugowania użyj polecenia e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.example.task"] w lldb. Wymusza ono uruchomienie zadania z pominięciem ograniczeń systemowych. Dostępna jest również flaga Xcode Symuluj Background Fetch w menu Debug.
Tak, BGTaskScheduler może uruchomić proces nawet jeśli aplikacja została wymuszenie zamknięta przez użytkownika. Jednak system może zastosować dodatkowe opóźnienia i nie wszystkie typy zadań gwarantują uruchomienie w tym scenariuszu.
System wywoła expirationHandler, przekazując zadaniu sygnał o konieczności zakończenia. Jeśli aplikacja zignoruje ten sygnał i będzie kontynuować pracę, iOS wymusi zakończenie procesu. Następnie system może obniżyć priorytet wszystkich zadań w tle aplikacji.
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ż