Background Task: concepte cheie, înregistrarea sarcinilor și execuția în fundal

Autor: IT Sectr Publicat: 2026-03-27 Timp de citire: 10 min

Background Task — mecanismul iOS care permite aplicației să finalizeze o operație începută după trecerea în modul fundal. Sistemul alocă timp limitat (până la 30 de secunde) pentru executarea sarcinii, după care aplicația este suspendată forțat. Conform Apple, 2026, utilizarea expiration handler este o cerință obligatorie pentru finalizarea corectă a sarcinii de fundal.

Principalele concluzii

  • Background Task — mecanism iOS pentru finalizarea operațiilor după trecerea aplicației în fundal.
  • beginBackgroundTask — metoda cheie a UIApplication pentru înregistrarea unei sarcini de fundal.
  • Expiration handler — bloc de cod apelat de sistem la expirarea timpului alocat.
  • Limitare 30 de secunde — timp standard pentru execuție, prelungire prin Background Modes.
  • UIApplication.shared.endBackgroundTask — apel obligatoriu pentru finalizarea corectă a sarcinii.

Ce este Background Task în iOS?

Background Task este un mecanism software iOS care permite aplicației să prelungească timpul de execuție după trecerea în modul fundal. Când utilizatorul minimizează aplicația, sistemul apelează UIApplicationDelegate.applicationDidEnterBackground. Dacă în acel moment se execută o operație critică (salvare date, trimitere cerere), aplicația poate solicita timp suplimentar prin beginBackgroundTask.

De ce sunt necesare Background Tasks

Fără utilizarea Background Task, aplicația este suspendată forțat după 3–5 secunde de la trecerea în fundal. Toate operațiile neterminate sunt întrerupte: datele nu se salvează, cererile de rețea se întrerup, stările se pierd. Background Task oferă aplicației până la 30 de secunde pentru finalizarea corectă a acestor operații.

  • Salvarea stării — scrierea datelor în CoreData, UserDefaults sau sistemul de fișiere.
  • Finalizarea cererilor de rețea — așteptarea răspunsului de la server și procesarea rezultatului.
  • Trimiterea analiticelor — transmiterea evenimentelor la serverul de analitică înainte de suspendare.
  • Curățarea resurselor — închiderea descriptorilor de fișiere, eliberarea memoriei.
  • Cache-ul — scrierea rezultatelor intermediare pentru restaurare la următoarea pornire.

Istoric și evoluție

beginBackgroundTask a apărut în iOS 4.0 — prima versiune care suporta multitasking. Înainte de iOS 4, aplicația se închidea complet la apăsarea butonului Home. Din iOS 7 au apărut Background Fetch și URLSession background configuration. Începând cu iOS 13, Apple recomandă BGTaskScheduler pentru proiecte noi, dar beginBackgroundTask rămâne relevant pentru operații de scurtă durată.

Cum funcționează beginBackgroundTask: ciclul de viață

beginBackgroundTask — metoda UIApplication care înregistrează o sarcină și returnează un identificator unic UIBackgroundTaskIdentifier. Sistemul mărește cronometrul de execuție în fundal. La expirarea timpului, este apelat expiration handler, după care aplicația trebuie să apeleze endBackgroundTask(identifier:) pentru finalizare corectă.

Procesul pas cu pas

Pasul 1 — aplicația primește notificarea didEnterBackground. Pasul 2 — se apelează beginBackgroundTask(expirationHandler:). Pasul 3 — se execută operația critică (salvare, cerere de rețea). Pasul 4 — la finalizare se apelează endBackgroundTask(identifier:). Dacă operația nu se finalizează în 30 de secunde — sistemul apelează expiration handler, iar aplicația trebuie să încheie sarcina imediat.

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

Proprietatea backgroundTimeRemaining returnează numărul de secunde rămase până la finalizarea forțată a sarcinii de fundal. Valoarea scade în timp real. Dacă aplicația nu este în fundal — returnează DBL_MAX. Folosește această proprietate pentru a adapta comportamentul: când rămân mai puțin de 5 secunde, întrerupe operațiile lungi și salvează progresul.

Sarcini multiple

Aplicația poate înregistra mai multe Background Task simultan. Fiecare sarcină primește propriul identificator. Timpul total de execuție se însumează — dacă sunt înregistrate 3 sarcini, aplicația poate primi până la 90 de secunde. Totuși, sistemul poate termina aplicația mai devreme dacă resursele sunt epuizate sau limita bateriei este depășită.

Expiration handler: gestionarea obligatorie a finalizării

Expiration handler este un bloc de cod apelat de sistem la expirarea timpului alocat pentru sarcina de fundal. Prezența expiration handler este o cerință obligatorie Apple. Fără el, aplicația poate fi terminată forțat de sistem, iar datele pot fi pierdute.

Ce trebuie să conțină expiration handler

Expiration handler trebuie să efectueze acțiuni minime pentru salvarea stării aplicației: să salveze datele curente în stocare persistentă, să apeleze endBackgroundTask cu identificatorul corespunzător și să seteze identificatorul la .invalid. În interiorul expiration handler este interzisă pornirea de noi operații lungi — timpul de execuție este limitat la 1–2 secunde.

swift
func handleExpiration() {
    // Salvăm progresul execuției
    saveProgressToUserDefaults()

    // Anulăm cererile de rețea active
    currentTask?.cancel()

    // Finalizăm Background Task
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

// Înregistrare cu expiration handler
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
    withName: "SaveDocument",
    expirationHandler: handleExpiration
)

Erori la lucrul cu expiration handler

Cea mai frecventă eroare este neapelarea endBackgroundTask în interiorul expiration handler. În acest caz, sistemul continuă să considere sarcina activă, aplicația nu trece în starea Suspended, iar bateria se descarcă. A doua eroare este pornirea de operații lungi în interiorul expiration handler. Sistemul poate termina aplicația înainte de finalizarea lor, iar datele se pierd.

Verificarea timpului rămas

În expiration handler, timpul de execuție este critic de scurt — de obicei mai puțin de 1 secundă. Prin urmare, în interiorul handler nu se pot executa: calcule complexe, cereri de rețea, scrierea de volume mari de date în CoreData. Doar operații atomice: scrierea unei chei în UserDefaults, setarea unui indicator de stare, apelarea endBackgroundTask.

Exemple de cod Background Task în Swift

Să analizăm implementarea completă a Background Task pentru salvarea unui document la trecerea aplicației în fundal. Exemplul include înregistrarea sarcinii, executarea operației cu verificarea timpului rămas și finalizarea corectă prin endBackgroundTask.

Salvarea documentului cu progres

La trecerea în fundal, aplicația inițiază salvarea unui document mare. Background Task oferă până la 30 de secunde pentru operație. Dacă timpul expiră — expiration handler salvează rezultatele intermediare. După finalizarea salvării, se apelează endBackgroundTask pentru eliberarea resurselor.

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
    }
}

Trimiterea datelor pe server

Cererile de rețea în fundal necesită atenție specială — expiration handler poate întrerupe cererea înainte de primirea răspunsului. Folosește URLSession cu dataTask și verifică backgroundTimeRemaining înainte de trimitere. Dacă au rămas mai puțin de 5 secunde — amână trimiterea până la următoarea reactivare a aplicației.

swift
func sendCriticalData(data: Data) {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Salvăm datele pentru retrimitere
        saveForRetry(data)
        self.endBackgroundTask()
    }

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

Monitorizarea timpului rămas

Pentru operații lungi, urmărește UIApplication.shared.backgroundTimeRemaining. Dacă valoarea scade sub prag (10 secunde), întrerupe operația curentă și pornește salvarea rezultatelor intermediare. Acest lucru permite finalizarea corectă a lucrului înainte de apelarea forțată a expiration handler.

Cele mai bune practici de utilizare a Background Task

Background Task este un mecanism puternic, dar utilizarea sa incorectă duce la probleme cu bateria și performanța. Respectarea recomandărilor Apple și a practicilor verificate ale comunității ajută la evitarea erorilor tipice și asigurarea funcționării stabile a aplicației.

Minimizarea timpului de execuție

Finalizează Background Task cât mai rapid posibil. Fiecare secundă de execuție în fundal consumă energie din baterie. Timpul optim — sub 5 secunde. Dacă operația durează mai mult — ia în considerare utilizarea BGTaskScheduler sau Background Modes. Nu prelungi sarcina artificial prin apeluri beginBackgroundTask fără necesitate reală.

Utilizarea corectă a identificatorilor

Stochează UIBackgroundTaskIdentifier ca proprietate a clasei sau structurii. Nu îl transmite niciodată ca variabilă globală — acest lucru duce la conflicte la sarcini multiple. Setează identificatorul la .invalid după apelarea endBackgroundTask pentru a preveni dubla finalizare.

Testarea Background Task

În Xcode Simulator comută aplicația în fundal prin butonul Home (Command + Shift + H). Folosește Debug — Simulate Background Fetch pentru testarea reactivării în fundal. Pentru a simula expirarea timpului, setează variabila de mediu BACKGROUND_TASK_SIMULATE_EXPIRATION = YES — expiration handler va fi apelat după 5 secunde.

swift
// Verificarea timpului rămas înainte de începerea operației
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
    // Timp insuficient — amână sarcina
    scheduleForNextLaunch()
    return
}

// Executarea operației cu controlul timpului
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
    saveProgress()
    self.endBackgroundTask()
}

Evită retain cycles

Expiration handler capturează self — acest lucru poate crea un retain cycle dacă backgroundTaskID este stocat ca proprietate a aceluiași obiect. Folosește [weak self] în închidere sau stochează identificatorul separat. Retain cycle duce la scurgeri de memorie — obiectul nu va fi eliberat până la terminarea aplicației.

Background Task vs BGTaskScheduler: compararea abordărilor

Odată cu lansarea iOS 13, Apple a introdus BGTaskScheduler — un înlocuitor modern pentru vechiul API Background Task. Ambele mecanisme rezolvă sarcini similare, dar BGTaskScheduler oferă mai mult control și flexibilitate. Înțelegerea diferențelor ajută la alegerea instrumentului potrivit pentru scenariul specific.

CaracteristicăBackground TaskBGTaskScheduler
Versiune iOS4.0+13.0+
Timp maxim30 de secunde30 s / 10 min (processing)
InițieredidEnterBackgroundPlanificare + sistem
Garanție execuțieDoar la trecerea în fundalÎn orice moment convenabil pentru sistem
Expiration handlerDa, obligatoriuDa, prin task.expirationHandler
InternetNecesar la pornireDisponibil prin requiresNetworkConnectivity
ÎncărcareNu este necesarăOpțional pentru processing

Când să folosești Background Task

beginBackgroundTask este potrivit pentru operații de scurtă durată care trebuie executate imediat la trecerea în fundal: salvare stare, finalizare cerere de rețea, cache de date. API-ul este simplu și nu necesită configurare Info.plist sau înregistrare de identificatori. Ideal pentru operații care durează mai puțin de 10 secunde.

Când să folosești BGTaskScheduler

BGTaskScheduler este potrivit pentru sarcini care pot fi executate în orice moment convenabil: sincronizare periodică, curățare cache, actualizare widgeturi. Sistemul alege singur momentul optim ținând cont de comportamentul utilizatorului și starea bateriei. Pentru operații lungi (până la 10 minute) folosește BGProcessingTask.

Utilizare comună

Ambele API pot fi folosite în aceeași aplicație. Background Task — pentru operații imediate la trecerea în fundal (salvare ciornă). BGTaskScheduler — pentru actualizări planificate (sincronizare la fiecare 6 ore). Împărțirea responsabilităților permite garantarea salvării corecte a datelor și a serviciului de fundal eficient energetic.

Întrebări frecvente

Se poate apela beginBackgroundTask în afara didEnterBackground?

Da, beginBackgroundTask poate fi apelat în orice moment al funcționării aplicației. Totuși, alocarea de timp de către sistem va începe doar după trecerea în fundal. Dacă aplicația este în prim-plan, apelul beginBackgroundTask nu are efect — backgroundTimeRemaining returnează DBL_MAX, iar sarcina va fi activată la trecerea în fundal.

Ce se întâmplă dacă nu se apelează endBackgroundTask?

Dacă nu se apelează endBackgroundTask, sistemul continuă să considere aplicația activă în fundal. După 30 de secunde va fi apelat expiration handler, dar dacă nici în el nu există endBackgroundTask — aplicația rămâne în memorie, consumând baterie. În iOS 13+ sistemul termină forțat o astfel de aplicație după 3 minute.

Cum se poate prelungi timpul Background Task peste 30 de secunde?

Timpul standard este de 30 de secunde. Se poate prelungi doar prin Background Modes: Audio (redare), Location (geolocație), Bluetooth (BLE). Sau prin BGProcessingTask (iOS 13+) — până la 10 minute cu condiția încărcării și Wi-Fi. beginBackgroundTask în sine nu oferă nicio modalitate de a mări limita.

Funcționează Background Task pe iPad?

Da, iPadOS suportă complet beginBackgroundTask cu aceleași limitări ca iOS. Pe iPad cu Stage Manager, aplicația poate rămâne în memorie mai mult timp — sistemul suspendă aplicațiile mai rar datorită cantității mai mari de RAM. Dar limita de 30 de secunde pentru sarcina de fundal rămâne.

Cum se depanează Background Task pe un dispozitiv real?

Conectează dispozitivul la Xcode, pornește aplicația, minimizeaz-o — în consolă vor apărea logurile sistemului. Folosește sysdiagnose pentru colectarea de loguri detaliate: declanșează sysdiagnose de pe dispozitiv (Volume Up + Down + Power). În Xcode Debug Navigator urmărește activitatea sarcinilor de fundal.

Rezumat

  • Background Task — mecanism iOS pentru finalizarea operațiilor după trecerea în fundal, disponibil din iOS 4.0.
  • beginBackgroundTask — metoda UIApplication care înregistrează sarcina și returnează un identificator pentru finalizarea acesteia.
  • Expiration handler — bloc de cod obligatoriu apelat de sistem la expirarea limitei de 30 de secunde.
  • endBackgroundTask — apel obligatoriu pentru finalizarea corectă a sarcinii; fără el, aplicația rămâne în memorie.
  • BGTaskScheduler — alternativă modernă (iOS 13+) cu planificare, două tipuri de sarcini și condiții de execuție.
  • backgroundTimeRemaining — proprietate pentru verificarea timpului rămas și adaptarea comportamentului sarcinii.
  • Folosește Background Task pentru operații imediate de scurtă durată și BGTaskScheduler pentru actualizări de fundal planificate în proiecte noi.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și