Background Fetch è un meccanismo iOS che risveglia periodicamente l'app in background per scaricare contenuti freschi. Il sistema analizza il comportamento dell'utente e seleziona le finestre ottimali per l'aggiornamento. Secondo Apple, 2026, l'app riceve da 30 a 120 secondi per eseguire l'operazione, dopo di che il sistema sospende o termina il processo.
Punti chiave
Background Fetch è un'API iOS che consente all'app di ricevere periodicamente nuovi dati in background. Introdotta per la prima volta in iOS 7 insieme al meccanismo Background App Refresh. L'obiettivo principale è che il contenuto sia aggiornato nel momento in cui l'utente apre l'app, senza dover attendere il caricamento.
Le notifiche push sono avviate dal server — questo invia un segnale al dispositivo e il sistema decide se risvegliare l'app. Background Fetch viene avviato da iOS stesso in base ai modelli di utilizzo del dispositivo. Push è più adatto per messaggi urgenti, mentre Fetch è per aggiornamenti programmati di contenuti (notizie, feed dei social media).
Background Fetch è uno dei vari meccanismi di esecuzione in background in iOS. BGAppRefreshTask (iOS 13+) esegue lo stesso compito ma con una pianificazione più flessibile. Background Modes (audio, posizione) sono per operazioni continue. Silent Push sono aggiornamenti avviati dal server. Fetch rimane rilevante per progetti che supportano iOS 12 e versioni precedenti.
iOS utilizza un algoritmo di apprendimento automatico per determinare il momento ottimale per risvegliare l'app. Il sistema analizza quando l'utente apre solitamente l'app, per quanto tempo la utilizza e con quale frequenza torna. Basandosi su questi dati, iOS calcola le finestre per Background Fetch.
Quando il sistema decide di risvegliare l'app, chiama il metodo application(_:performFetchWithCompletionHandler:) in AppDelegate. L'app deve caricare una quantità minima di nuovi dati e chiamare il completion handler con uno dei tre stati: .newData (dati caricati), .noData (nessun nuovo dato) o .failed (errore). Lo stato influisce sulla frequenza dei futuri risvegli.
Lo stato .newData comunica al sistema che l'aggiornamento è stato utile — iOS può aumentare la frequenza dei risvegli. .noData indica che non ci sono dati — la frequenza rimane invariata o diminuisce. .failed segnala un problema — il sistema riduce la frequenza per risparmiare batteria. L'enfasi dovrebbe essere su uno stato onesto, non sul forzare .newData.
| Stato | Significato | Impatto |
|---|---|---|
| .newData | Dati caricati con successo | La frequenza può aumentare |
| .noData | Il controllo non ha prodotto nuovi dati | La frequenza rimane invariata |
| .failed | Errore di rete o del server | La frequenza diminuisce |
Per abilitare Background Fetch sono necessari due passaggi: attivare la capability in Xcode e impostare l'intervallo minimo nel codice. La capability si trova in Target — Signing & Capabilities — Background Modes — spuntare la casella Background Fetch. Senza questo passaggio, il sistema non risveglierà l'app.
Il metodo UIApplication.shared.setMinimumBackgroundFetchInterval imposta il tempo minimo in secondi tra le chiamate Fetch. Il valore UIApplication.backgroundFetchIntervalMinimum (circa 15 minuti) indica al sistema di risvegliare l'app il più spesso possibile in modo energeticamente efficiente. Impostare l'intervallo in application(_:didFinishLaunchingWithOptions:) è una pratica standard.
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey : Any]?
)-> Bool {
UIApplication.shared.setMinimumBackgroundFetchInterval(
UIApplication.backgroundFetchIntervalMinimum
)
return true
}
Quando si abilita Background Fetch in Xcode, questo aggiorna automaticamente Info.plist — aggiunge la chiave UIBackgroundModes con il valore fetch. Questo è un passaggio obbligatorio: senza di esso, l'app non riceverà la chiamata performFetchWithCompletionHandler. È possibile verificare tramite P list Source o Build Settings.
Vediamo un'implementazione completa di Background Fetch per un'app di notizie. L'implementazione include il caricamento dei dati, la memorizzazione nella cache e la chiamata al completion handler. Il codice viene eseguito in AppDelegate — l'unico posto in cui il sistema chiama fetch.
func application(
_ application: UIApplication,
performFetchWithCompletionHandler handler: @escaping (UIBackgroundFetchResult) -> Void
) {
let url = URL(string: "https://api.example.com/latest")!
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
handler(.failed)
return
}
do {
let articles = try JSONDecoder().decode([Article].self, from: data)
cacheArticles(articles)
handler(articles.isEmpty ? .noData : .newData)
} catch {
handler(.failed)
}
}.resume()
}
Dopo aver caricato i dati tramite Background Fetch, è necessario salvarli nell'archivio locale — CoreData, UserDefaults o File Manager. All'apertura dell'app, i dati dovrebbero già essere disponibili. Utilizzare CoreData con un contesto in background per una scrittura thread-safe. Dopo il salvataggio, aggiornare l'interfaccia utente sul thread principale.
func cacheArticles(_ articles: [Article]) {
let container = NSPersistentContainer(name: "AppModel")
container.performBackgroundTask { context in
articles.forEach { article in
let entity = ArticleEntity(context: context)
entity.id = Int64(article.id)
entity.title = article.title
entity.body = article.body
}
try? context.save()
}
}
Per i test, utilizzare il Simulatore — selezionare Debug — Simulate Background Fetch in Xcode. Su un dispositivo fisico, è necessario attendere che il sistema decida di eseguire un fetch. Per velocizzare, è possibile impostare l'intervallo minimo a 1 minuto, ma il sistema potrebbe ignorarlo quando la batteria è scarica.
Background Fetch ha diverse limitazioni importanti da considerare nella progettazione dell'architettura dell'app. La principale è che il sistema controlla completamente la frequenza delle chiamate e lo sviluppatore non può garantirla. Anche con un intervallo minimo impostato, il sistema potrebbe non chiamare fetch per ore.
Il sistema alloca tempo limitato all'app per eseguire l'attività — generalmente fino a 30 secondi. Se l'app non chiama il completion handler entro questo tempo, il sistema termina forzatamente il processo e riduce la frequenza dei futuri risvegli. Tutte le richieste di rete devono essere compatte — non più di 1-2 per chiamata.
iOS tiene conto del livello della batteria nella pianificazione di Background Fetch. Quando la carica è inferiore al 20%, la frequenza dei risvegli diminuisce. Quando la Modalità risparmio energetico è attiva, il sistema può disabilitare completamente gli aggiornamenti in background per tutte le app. L'utente può anche disabilitare Background App Refresh per un'app specifica nelle impostazioni.
URLSession avviata da Background Fetch funziona in modalità standard — senza supporto per sessioni in background. Per download di grandi dimensioni, utilizzare URLSession con configurazione in background. Il sistema continuerà il download anche dopo la fine del fetch, ma l'avanzamento non verrà tracciato fino al successivo risveglio.
A partire da iOS 13, Apple raccomanda BGTaskScheduler come sostituto di Background Fetch. BGTaskScheduler offre una pianificazione più flessibile, due tipi di attività (refresh e processing) e registrazione delle attività con identificatori. La migrazione comprende diversi passaggi ed è raccomandata per tutti i nuovi progetti.
Il primo passaggio è definire gli identificatori delle attività in Info.plist tramite la chiave BGTaskSchedulerPermittedIdentifiers. Il secondo è registrare le attività in AppDelegate tramite BGTaskScheduler.shared.register. Il terzo è sostituire la chiamata performFetchWithCompletionHandler con il handler passato a register. Il quarto è chiamare submit per pianificare l'attività.
// Prima (Background Fetch)
UIApplication.shared.setMinimumBackgroundFetchInterval(
UIApplication.backgroundFetchIntervalMinimum
)
// Dopo la migrazione (BGTaskScheduler)
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.example.refresh",
using: nil
) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
let request = BGAppRefreshTaskRequest(
identifier: "com.example.refresh"
)
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
try? BGTaskScheduler.shared.submit(request)
BGTaskScheduler offre più controllo: BGProcessingTask per operazioni lunghe (fino a 10 minuti), condizioni di esecuzione tramite requiresNetworkConnectivity e requiresExternalPower, e un expiration handler per la terminazione graduale. Il sistema analizza anche l'utilizzo dell'app, ma lo sviluppatore può impostare requisiti più precisi.
Se l'app supporta iOS 12 e versioni precedenti, Background Fetch rimane l'unica opzione per gli aggiornamenti periodici. BGTaskScheduler è disponibile solo da iOS 13+. In questo caso, utilizzare un wrapper: verificare la disponibilità tramite if #available(iOS 13, *) e chiamare l'API corrispondente.
Domande frequenti
La frequenza esatta non è documentata e dipende dal comportamento dell'utente. Il sistema analizza quanto spesso l'utente apre l'app e regola la frequenza di conseguenza. In media, con un uso attivo, fetch può essere chiamato 1–3 volte all'ora. Con un uso poco frequente — 1–2 volte al giorno.
Controllare tre condizioni: la capability Background Fetch è abilitata in Xcode, minimumBackgroundFetchInterval è impostato e l'utente non ha disabilitato Background App Refresh per l'app nelle impostazioni. Controllare anche che il dispositivo non sia in Modalità risparmio energetico e che il livello della batteria sia superiore al 20%.
Background Fetch è la vecchia API (iOS 7), BGAppRefreshTask è la nuova API (iOS 13+). BGAppRefreshTask offre più controllo: expiration handler, capacità di riprogrammazione e verifica dello stato. Background Fetch è più semplice da implementare ma meno flessibile. Apple raccomanda di utilizzare BGAppRefreshTask per i nuovi progetti.
Non raccomandato. Background Fetch è limitato nel tempo (fino a 30 secondi). Per download di grandi dimensioni, utilizzare URLSession con configurazione in background — il sistema continuerà il download anche dopo la fine del fetch. Un'alternativa è BGProcessingTask (iOS 13+), che consente fino a 10 minuti e condizioni di ricarica.
Sì, ogni risveglio consuma energia per accendere il processore, inizializzare lo stack di rete e caricare i dati. iOS ottimizza la frequenza per ridurre al minimo l'impatto. Con un'implementazione corretta — caricamento solo di nuovi dati, chiamata rapida del completion handler — l'impatto sulla batteria è minimo.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche