Background Task, bir uygulamanın arka plana geçtikten sonra bir işlemi tamamlamasına izin veren bir iOS mekanizmasıdır. Sistem, görevi yürütmek için sınırlı süre (30 saniyeye kadar) ayırır ve ardından uygulama zorla askıya alınır. Apple, 2026'ya göre, bir expiration handler kullanmak, arka plan görevini doğru şekilde tamamlamak için zorunlu bir gerekliliktir.
Önemli Noktalar
Background Task, bir uygulamanın arka plana geçtikten sonra yürütme süresini uzatmasına izin veren programlanabilir bir iOS mekanizmasıdır. Kullanıcı uygulamayı küçülttüğünde, sistem UIApplicationDelegate.applicationDidEnterBackground öğesini çağırır. O anda kritik bir işlem (veri kaydetme, istek gönderme) yürütülüyorsa, uygulama beginBackgroundTask aracılığıyla ek süre talep edebilir.
Background Task kullanılmazsa, uygulama arka plana geçtikten sonra 3–5 saniye içinde zorla askıya alınır. Tamamlanmamış tüm işlemler kesintiye uğrar: veriler kaydedilmez, ağ istekleri iptal edilir, durumlar kaybolur. Background Task, uygulamaya bu işlemleri doğru şekilde tamamlaması için 30 saniyeye kadar süre verir.
beginBackgroundTask, çoklu görevi destekleyen ilk sürüm olan iOS 4.0'da ortaya çıktı. iOS 4'ten önce, Ana Ekran düğmesine basıldığında uygulama tamamen sonlandırılıyordu. iOS 7, Background Fetch ve URLSession arka plan yapılandırmasını tanıttı. iOS 13'ten itibaren Apple, yeni projeler için BGTaskScheduler'ı önermektedir, ancak beginBackgroundTask kısa vadeli işlemler için geçerliliğini korumaktadır.
beginBackgroundTask, bir görevi kaydeden ve benzersiz bir UIBackgroundTaskIdentifier döndüren UIApplication yöntemidir. Sistem arka plan yürütme zamanlayıcısını artırır. Süre dolduğunda expiration handler çağrılır ve ardından uygulama görevi doğru şekilde tamamlamak için endBackgroundTask(identifier:) çağırmalıdır.
Adım 1 — uygulama didEnterBackground bildirimini alır. Adım 2 — beginBackgroundTask(expirationHandler:) çağrılır. Adım 3 — kritik işlem (kaydetme, ağ isteği) yürütülür. Adım 4 — tamamlandığında, endBackgroundTask(identifier:) çağrılır. İşlem 30 saniye içinde tamamlanmazsa — sistem expiration handler'ı çağırır ve uygulama görevi derhal sonlandırmalıdır.
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
}
backgroundTimeRemaining özelliği, arka plan görevi zorla sonlandırılmadan önce kalan saniye sayısını döndürür. Değer gerçek zamanlı olarak azalır. Uygulama arka planda değilse — DBL_MAX döndürür. Davranışı uyarlamak için bu özelliği kullanın: 5 saniyeden az kaldığında, uzun süren işlemleri kesintiye uğratın ve ilerlemeyi kaydedin.
Bir uygulama aynı anda birden çok Background Task kaydedebilir. Her görev kendi tanımlayıcısını alır. Toplam yürütme süresi kümülatiftir — 3 görev kaydedilirse, uygulama 90 saniyeye kadar süre alabilir. Ancak, kaynaklar tükenirse veya pil sınırı aşılırsa sistem uygulamayı daha erken sonlandırabilir.
Expiration handler, arka plan görevi için ayrılan süre dolduğunda sistemin çağırdığı bir kod bloğudur. Bir expiration handler'a sahip olmak Apple'ın zorunlu bir gerekliliğidir. Bu olmadan, uygulama sistem tarafından zorla sonlandırılabilir ve veriler kaybolabilir.
Expiration handler, uygulama durumunu kaydetmek için minimum eylemler gerçekleştirmelidir: mevcut verileri kalıcı depolamaya kaydetmeli, ilgili tanımlayıcıyla endBackgroundTask çağırmalı ve tanımlayıcıyı .invalid olarak ayarlamalıdır. Expiration handler içinde yeni uzun süreli işlemler başlatmak yasaktır — yürütme süresi 1–2 saniye ile sınırlıdır.
func handleExpiration() {
// Yürütme ilerlemesi kaydediliyor
saveProgressToUserDefaults()
// Aktif ağ istekleri iptal ediliyor
currentTask?.cancel()
// Background Task sonlandırılıyor
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
// Expiration handler ile kayıt
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
withName: "SaveDocument",
expirationHandler: handleExpiration
)
En yaygın hata, expiration handler içinde endBackgroundTask çağırmamaktır. Bu durumda, sistem görevi aktif olarak değerlendirmeye devam eder, uygulama Askıya Alındı durumuna geçmez ve pil tükenir. İkinci hata, expiration handler içinde uzun süreli işlemler başlatmaktır. Sistem bunlar tamamlanmadan uygulamayı sonlandırabilir ve veriler kaybolur.
Expiration handler'da, yürütme süresi kritik derecede sınırlıdır — tipik olarak 1 saniyeden az. Bu nedenle, handler içinde şunlar yapılamaz: karmaşık hesaplamalar, ağ istekleri, CoreData'ya büyük miktarda veri yazma. Yalnızca atomik işlemler: UserDefaults'a tek bir anahtar yazma, durum bayrağı ayarlama, endBackgroundTask çağırma.
Uygulama arka plana geçtiğinde bir belgeyi kaydetmek için eksiksiz bir Background Task uygulamasını inceleyelim. Örnek, görev kaydı, kalan süre kontrolü ile işlem yürütme ve endBackgroundTask aracılığıyla doğru tamamlama içerir.
Arka plana geçerken, uygulama büyük bir belgenin kaydedilmesini başlatır. Background Task, işlem için 30 saniyeye kadar süre sağlar. Süre dolarsa — expiration handler ara sonuçları kaydeder. Kaydetme tamamlandıktan sonra, kaynakları serbest bırakmak için endBackgroundTask çağrılır.
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
}
}
Arka planda ağ istekleri özel dikkat gerektirir — expiration handler, yanıt almadan önce isteği kesintiye uğratabilir. dataTask ile URLSession kullanın ve göndermeden önce backgroundTimeRemaining'i kontrol edin. 5 saniyeden az kaldıysa — göndermeyi bir sonraki uygulama uyanışına kadar erteleyin.
func sendCriticalData(data: Data) {
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
// Yeniden gönderme için veri kaydediliyor
saveForRetry(data)
self.endBackgroundTask()
}
let task = URLSession.shared.dataTask(with: request) { _, _, error in
if error != nil {
saveForRetry(data)
}
self.endBackgroundTask()
}
task.resume()
}
Uzun süreli işlemler için UIApplication.shared.backgroundTimeRemaining öğesini izleyin. Değer bir eşiğin (10 saniye) altına düşerse, mevcut işlemi kesintiye uğratın ve ara sonuçları kaydetmeye başlayın. Bu, expiration handler zorla çağrılmadan önce doğru şekilde tamamlanmasını sağlar.
Background Task güçlü bir mekanizmadır, ancak yanlış kullanımı pil ve performans sorunlarına yol açar. Apple'ın önerilerini ve topluluğun kanıtlanmış uygulamalarını takip etmek, yaygın hatalardan kaçınmaya ve istikrarlı uygulama çalışması sağlamaya yardımcı olacaktır.
Background Task'ı mümkün olduğunca çabuk tamamlayın. Arka plan yürütmenin her saniyesi pil gücü tüketir. En uygun süre — 5 saniyeden az. İşlem daha uzun sürüyorsa — BGTaskScheduler veya Background Modes kullanmayı düşünün. Gerçek bir ihtiyaç olmadan beginBackgroundTask çağrılarıyla görevi yapay olarak uzatmayın.
UIBackgroundTaskIdentifier'ı bir sınıf veya yapı özelliği olarak saklayın. Asla global bir değişken olarak iletmeyin — bu, birden çok görevle çakışmalara yol açar. Çift tamamlamayı önlemek için endBackgroundTask'ı çağırdıktan sonra tanımlayıcıyı .invalid olarak ayarlayın.
Xcode Simulator'da, Ana Ekran düğmesi (Command + Shift + H) aracılığıyla uygulamayı arka plana geçirin. Arka plan uyanmasını test etmek için Debug — Simulate Background Fetch kullanın. Süre sonunu simüle etmek için Ortam Değişkenini BACKGROUND_TASK_SIMULATE_EXPIRATION = YES olarak ayarlayın — expiration handler 5 saniye içinde çağrılacaktır.
// İşlem başlatılmadan önce kalan süre kontrol ediliyor
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
// Yeterli süre yok — görev ertelensin
scheduleForNextLaunch()
return
}
// Zaman kontrolü ile işlem yürütülüyor
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
saveProgress()
self.endBackgroundTask()
}
Expiration handler self öğesini yakalar — backgroundTaskID aynı nesnenin bir özelliği olarak saklanıyorsa bu bir retain döngüsü oluşturabilir. Closure'da [weak self] kullanın veya tanımlayıcıyı ayrı olarak saklayın. Bir retain döngüsü bellek sızıntısına yol açar — nesne, uygulama sonlanana kadar serbest bırakılmaz.
iOS 13'ün piyasaya sürülmesiyle Apple, BGTaskScheduler'ı tanıttı — eski Background Task API'sinin modern bir yedeği. Her iki mekanizma da benzer görevleri çözer, ancak BGTaskScheduler daha fazla kontrol ve esneklik sağlar. Farklılıkları anlamak, belirli bir senaryo için doğru aracı seçmeye yardımcı olacaktır.
| Özellik | Background Task | BGTaskScheduler |
|---|---|---|
| iOS Sürümü | 4.0+ | 13.0+ |
| Maks. Süre | 30 saniye | 30 sn / 10 dk (processing) |
| Başlatma | didEnterBackground | Zamanlama + sistem |
| Yürütme Garantisi | Yalnızca arka plana geçerken | Sistem için uygun herhangi bir zamanda |
| Expiration handler | Evet, zorunlu | Evet, task.expirationHandler aracılığıyla |
| İnternet | Başlangıçta gerekli | requiresNetworkConnectivity ile kullanılabilir |
| Şarj | Gerekli değil | Processing için isteğe bağlı |
beginBackgroundTask, arka plana geçerken hemen yürütülmesi gereken kısa vadeli işlemler için uygundur: durum kaydetme, ağ isteğini tamamlama, verileri önbelleğe alma. API basittir ve Info.plist yapılandırması veya tanımlayıcı kaydı gerektirmez. 10 saniyeden az süren işlemler için idealdir.
BGTaskScheduler, uygun herhangi bir zamanda yürütülebilecek görevler için uygundur: periyodik senkronizasyon, önbellek temizleme, widget güncellemeleri. Sistem, kullanıcı davranışını ve pil durumunu dikkate alarak en uygun zamanı kendisi seçer. Uzun süreli işlemler (10 dakikaya kadar) için BGProcessingTask kullanın.
Her iki API de aynı uygulamada kullanılabilir. Background Task — arka plana geçerken acil işlemler için (taslak kaydetme). BGTaskScheduler — planlı güncellemeler için (6 saatte bir senkronizasyon). Sorumlulukların ayrılması, verilerin doğru şekilde korunmasını ve enerji verimli arka plan bakımını sağlar.
Sıkça Sorulan Sorular
Evet, beginBackgroundTask uygulama yürütmesi sırasında herhangi bir noktada çağrılabilir. Ancak, sistem süresi tahsisi yalnızca arka plana geçtikten sonra başlayacaktır. Uygulama ön plandaysa, beginBackgroundTask çağrısının hiçbir etkisi yoktur — backgroundTimeRemaining DBL_MAX döndürür ve görev arka plana geçildiğinde etkinleştirilir.
endBackgroundTask çağrılmazsa, sistem uygulamayı arka planda aktif olarak değerlendirmeye devam eder. 30 saniye sonra expiration handler çağrılır, ancak bunda da endBackgroundTask yoksa — uygulama bellekte kalır ve pili tüketir. iOS 13+'ta sistem, bu tür bir uygulamayı 3 dakika sonra zorla sonlandırır.
Standart süre 30 saniyedir. Yalnızca Background Modes: Ses (oynatma), Konum (coğrafi konum), Bluetooth (BLE) aracılığıyla uzatılabilir. Veya BGProcessingTask (iOS 13+) aracılığıyla — şarj ve Wi-Fi ile 10 dakikaya kadar. beginBackgroundTask'ın kendisi sınırı artırmanın bir yolunu sağlamaz.
Evet, iPadOS, iOS ile aynı sınırlamalarla beginBackgroundTask'ı tam olarak destekler. Stage Manager'lı iPad'de uygulama bellekte daha uzun süre kalabilir — sistem, daha büyük RAM nedeniyle uygulamaları daha az sıklıkta askıya alır. Ancak arka plan görevi için 30 saniyelik sınır devam eder.
Cihazı Xcode'a bağlayın, uygulamayı başlatın, küçültün — konsolda sistem günlükleri görünecektir. Ayrıntılı günlükler toplamak için sysdiagnose kullanın: cihazdan sysdiagnose'u zorla tetikleyin (Ses Yükseltme + Ses Kısma + Güç). Xcode Debug Navigator'da arka plan görev aktivitesini izleyin.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun