Background Task — mechanismus iOS, který umožňuje aplikaci dokončit započatou operaci po přechodu do režimu na pozadí. Systém přiděluje omezený čas (až 30 sekund) na provedení úkolu, poté je aplikace násilně pozastavena. Podle Apple, 2026 je použití expiration handler povinným požadavkem pro správné dokončení úlohy na pozadí.
Hlavní body
Background Task je softwarový mechanismus iOS, který umožňuje aplikaci prodloužit dobu provádění po přechodu do režimu na pozadí. Když uživatel minimalizuje aplikaci, systém volá UIApplicationDelegate.applicationDidEnterBackground. Pokud v tu chvíli probíhá kritická operace (ukládání dat, odesílání požadavku), může aplikace požádat o dodatečný čas prostřednictvím beginBackgroundTask.
Bez použití Background Task je aplikace násilně pozastavena 3–5 sekund po přechodu na pozadí. Všechny nedokončené operace jsou přerušeny: data se neukládají, síťové požadavky se přerušují, stavy se ztrácejí. Background Task dává aplikaci až 30 sekund pro správné dokončení těchto operací.
beginBackgroundTask se objevil v iOS 4.0 — prvním vydání podporujícím multitasking. Před iOS 4 se aplikace při stisknutí tlačítka Home zcela zavírala. Od iOS 7 se objevily Background Fetch a URLSession background configuration. Počínaje iOS 13 Apple doporučuje BGTaskScheduler pro nové projekty, ale beginBackgroundTask zůstává relevantní pro krátkodobé operace.
beginBackgroundTask — metoda UIApplication, která registruje úlohu a vrací unikátní identifikátor UIBackgroundTaskIdentifier. Systém prodlužuje časovač provádění na pozadí. Po vypršení času je volán expiration handler, poté musí aplikace zavolat endBackgroundTask(identifier:) pro správné dokončení.
Krok 1 — aplikace obdrží oznámení didEnterBackground. Krok 2 — je voláno beginBackgroundTask(expirationHandler:). Krok 3 — provádí se kritická operace (ukládání, síťový požadavek). Krok 4 — po dokončení je voláno endBackgroundTask(identifier:). Pokud operace neskončí do 30 sekund — systém volá expiration handler a aplikace musí úlohu okamžitě ukončit.
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
}
Vlastnost backgroundTimeRemaining vrací počet sekund zbývajících do násilného ukončení úlohy na pozadí. Hodnota se v reálném čase snižuje. Pokud aplikace není na pozadí — vrací DBL_MAX. Použijte tuto vlastnost k přizpůsobení chování: když zbývá méně než 5 sekund, přerušte dlouhé operace a uložte průběh.
Aplikace může registrovat několik Background Task současně. Každá úloha dostává vlastní identifikátor. Celková doba provádění se sčítá — pokud jsou registrovány 3 úlohy, aplikace může získat až 90 sekund. Systém však může aplikaci ukončit dříve, pokud dojdou zdroje nebo je překročen limit baterie.
Expiration handler je blok kódu volaný systémem při vypršení přiděleného času pro úlohu na pozadí. Přítomnost expiration handler je povinným požadavkem Apple. Bez něj může být aplikace systémem násilně ukončena a data mohou být ztracena.
Expiration handler by měl provést minimální akce pro uložení stavu aplikace: uložit aktuální data do trvalého úložiště, zavolat endBackgroundTask s příslušným identifikátorem a nastavit identifikátor na .invalid. Uvnitř expiration handler je zakázáno spouštět nové dlouhé operace — doba provádění je omezena na 1–2 sekundy.
func handleExpiration() {
// Ukládáme průběh provádění
saveProgressToUserDefaults()
// Rušíme aktivní síťové požadavky
currentTask?.cancel()
// Dokončujeme Background Task
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
// Registrace s expiration handler
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
withName: "SaveDocument",
expirationHandler: handleExpiration
)
Nejčastější chybou je nevolání endBackgroundTask uvnitř expiration handler. V tomto případě systém nadále považuje úlohu za aktivní, aplikace nepřechází do stavu Suspended a baterie se vybíjí. Druhou chybou je spouštění dlouhých operací uvnitř expiration handler. Systém může aplikaci ukončit před jejich dokončením a data budou ztracena.
V expiration handler je doba provádění kriticky krátká — obvykle méně než 1 sekunda. Proto uvnitř handler nelze provádět: složité výpočty, síťové požadavky, zápis velkých objemů dat do CoreData. Pouze atomické operace: zápis jednoho klíče do UserDefaults, nastavení stavového příznaku, volání endBackgroundTask.
Podívejme se na úplnou implementaci Background Task pro uložení dokumentu při přechodu aplikace na pozadí. Příklad zahrnuje registraci úlohy, provedení operace s kontrolou zbývajícího času a správné dokončení pomocí endBackgroundTask.
Při přechodu na pozadí aplikace zahájí ukládání velkého dokumentu. Background Task poskytuje až 30 sekund pro operaci. Pokud čas vyprší — expiration handler uloží mezivýsledky. Po dokončení ukládání je voláno endBackgroundTask pro uvolnění zdrojů.
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
}
}
Požadavky na síť na pozadí vyžadují zvláštní pozornost — expiration handler může přerušit požadavek před obdržením odpovědi. Použijte URLSession s dataTask a před odesláním zkontrolujte backgroundTimeRemaining. Pokud zbývá méně než 5 sekund — odložte odeslání do příštího probuzení aplikace.
func sendCriticalData(data: Data) {
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
// Ukládáme data pro opětovné odeslání
saveForRetry(data)
self.endBackgroundTask()
}
let task = URLSession.shared.dataTask(with: request) { _, _, error in
if error != nil {
saveForRetry(data)
}
self.endBackgroundTask()
}
task.resume()
}
Pro dlouhé operace sledujte UIApplication.shared.backgroundTimeRemaining. Pokud hodnota klesne pod práh (10 sekund), přerušte aktuální operaci a spusťte ukládání mezivýsledků. To umožňuje správné dokončení práce před násilným voláním expiration handler.
Background Task je mocný mechanismus, ale jeho nesprávné použití vede k problémům s baterií a výkonem. Dodržování doporučení Apple a osvědčených postupů komunity pomáhá vyhnout se typickým chybám a zajistit stabilní provoz aplikace.
Dokončete Background Task co nejrychleji. Každá sekunda provádění na pozadí spotřebovává energii baterie. Optimální doba — méně než 5 sekund. Pokud operace trvá déle — zvažte použití BGTaskScheduler nebo Background Modes. Neprodlužujte úlohu uměle pomocí volání beginBackgroundTask bez skutečné potřeby.
Ukládejte UIBackgroundTaskIdentifier jako vlastnost třídy nebo struktury. Nikdy jej nepředávejte jako globální proměnnou — to vede ke konfliktům při více úlohách. Nastavte identifikátor na .invalid po volání endBackgroundTask, abyste zabránili dvojímu dokončení.
V Xcode Simulator přepněte aplikaci na pozadí tlačítkem Home (Command + Shift + H). Použijte Debug — Simulate Background Fetch pro testování probuzení na pozadí. Pro simulaci vypršení času nastavte proměnnou prostředí BACKGROUND_TASK_SIMULATE_EXPIRATION = YES — expiration handler bude volán po 5 sekundách.
// Kontrola zbývajícího času před zahájením operace
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
// Nedostatek času — odložit úlohu
scheduleForNextLaunch()
return
}
// Provádění operace s kontrolou času
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
saveProgress()
self.endBackgroundTask()
}
Expiration handler zachycuje self — to může vytvořit retain cycle, pokud je backgroundTaskID uložen jako vlastnost stejného objektu. Použijte [weak self] v uzávěru nebo ukládejte identifikátor zvlášť. Retain cycle vede k úniku paměti — objekt nebude uvolněn až do ukončení aplikace.
S vydáním iOS 13 Apple představil BGTaskScheduler — moderní náhradu starého API Background Task. Oba mechanismy řeší podobné úkoly, ale BGTaskScheduler poskytuje větší kontrolu a flexibilitu. Pochopení rozdílů pomáhá vybrat správný nástroj pro konkrétní scénář.
| Vlastnost | Background Task | BGTaskScheduler |
|---|---|---|
| Verze iOS | 4.0+ | 13.0+ |
| Max. čas | 30 sekund | 30 s / 10 min (processing) |
| Iniciace | didEnterBackground | Plánování + systém |
| Záruka provedení | Pouze při přechodu na pozadí | Kdykoli to systému vyhovuje |
| Expiration handler | Ano, povinný | Ano, přes task.expirationHandler |
| Internet | Vyžadován při spuštění | Dostupný přes requiresNetworkConnectivity |
| Nabíjení | Není vyžadováno | Volitelné pro processing |
beginBackgroundTask je vhodný pro krátkodobé operace, které je třeba provést okamžitě při přechodu na pozadí: uložení stavu, dokončení síťového požadavku, ukládání dat do mezipaměti. API je jednoduché a nevyžaduje konfiguraci Info.plist ani registraci identifikátorů. Ideální pro operace trvající méně než 10 sekund.
BGTaskScheduler je vhodný pro úkoly, které mohou být provedeny kdykoli: periodická synchronizace, čištění mezipaměti, aktualizace widgetů. Systém sám vybírá optimální čas s ohledem na chování uživatele a stav baterie. Pro dlouhé operace (až 10 minut) použijte BGProcessingTask.
Oba API lze použít v jedné aplikaci. Background Task — pro okamžité operace při přechodu na pozadí (uložení konceptu). BGTaskScheduler — pro plánované aktualizace (synchronizace každých 6 hodin). Rozdělení odpovědnosti umožňuje zaručit správné ukládání dat a energeticky efektivní službu na pozadí.
Často kladené otázky
Ano, beginBackgroundTask lze zavolat kdykoli během provozu aplikace. Systémové přidělení času však začne až po přechodu na pozadí. Pokud je aplikace v popředí, volání beginBackgroundTask nemá účinek — backgroundTimeRemaining vrací DBL_MAX a úloha bude aktivována při přechodu na pozadí.
Pokud nezavoláte endBackgroundTask, systém nadále považuje aplikaci za aktivní na pozadí. Po 30 sekundách bude volán expiration handler, ale pokud ani v něm není endBackgroundTask — aplikace zůstává v paměti a spotřebovává baterii. V iOS 13+ systém takovou aplikaci po 3 minutách násilně ukončí.
Standardní čas je 30 sekund. Prodloužit jej lze pouze pomocí Background Modes: Audio (přehrávání), Location (geolokace), Bluetooth (BLE). Nebo pomocí BGProcessingTask (iOS 13+) — až 10 minut při nabíjení a Wi-Fi. beginBackgroundTask sám o sobě neposkytuje způsob, jak limit zvýšit.
Ano, iPadOS plně podporuje beginBackgroundTask se stejnými omezeními jako iOS. Na iPadu se Stage Manager může aplikace zůstat v paměti déle — systém kvůli většímu množství RAM aplikace pozastavuje méně často. Ale limit 30 sekund pro úlohu na pozadí zůstává.
Připojte zařízení k Xcode, spusťte aplikaci, minimalizujte ji — v konzole se objeví systémové protokoly. Použijte sysdiagnose pro sběr podrobných protokolů: vynuťte sysdiagnose ze zařízení (Volume Up + Down + Power). V Xcode Debug Navigator sledujte aktivitu úloh na pozadí.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také