Suspended — mi ez, alkalmazás befagyasztása a háttérben iOS-ben

Szerző: IT Sectr Megjelenés: 2026-03-03 Olvasási idő: 11 perc

Suspended — az iOS-alkalmazás életciklusának felfüggesztett állapota, amelyben az alkalmazás a memóriában van befagyasztva, de nem hajt végre kódot. Megmutatjuk, hogyan működik a Suspended, milyen kockázatokat hordoz az alkalmazás háttérben történő befagyasztása, hogyan kezeli az iOS a Suspended alkalmazások kiürítését, és hogyan valósítsuk meg a state restoration-t a zökkenőmentes helyreállításhoz a Suspended-ből való visszatérés után.

Főbb pontok

  • Suspended — az alkalmazás be van fagyasztva a memóriában, a kód nem fut, a UI-verem megmarad
  • iOS Suspended — egyedi állapot, amely nem létezik Androidban; a folyamat létezik, de nem aktív
  • Kiürítés — memóriahiány esetén a Suspended alkalmazások törlődnek elsőként, a memóriában lévő adatok elvesznek
  • State Restoration — iOS-mechanizmus a UI-verem mentésére és helyreállítására kiürítés után
  • didEnterBackground — az utolsó metódus, amely garantáltan meghívódik a Suspended előtt

Suspended — milyen állapot ez

Suspended — az iOS-alkalmazás életciklusának az az állapota, amelyben az alkalmazás a készülék operatív memóriájában található, de nem hajt végre semmilyen kódot. Ez a végső állapot a teljes befejezés előtt: az alkalmazás a Background-ból Suspended-be lép az összes háttérfeladat befejezése után vagy az időtúllépés lejártakor. Suspended-ben az alkalmazás teljesen le van fagyasztva — az összes szál fel van függesztve, az időzítők nem működnek, hálózati tevékenység nincs.

Suspended — az iOS egyedi jellemzője, amely nem található meg az Android szabványos életciklusában. Az ok a folyamatkezelés eltérő architektúrája. Az iOS megőrzi az alkalmazás képét a memóriában (analóg a desktop hibernálással), hogy a felhasználó visszatérésekor azonnal helyreállítsa a felületet hideg indítás nélkül. Az Android nem rendelkezik Suspended-del — a folyamat vagy létezik és képes kódot végrehajtani (Background), vagy befejeződött (Not Running), bár az Android az LMK-n keresztül felfüggesztheti a szálak végrehajtását.

A felhasználó számára a Suspended azonnali helyreállításnak tűnik: az App Switcher-en keresztül váltogat az alkalmazások között, és minden alkalmazás ott nyílik meg, ahol hagyta. Ez azt az illúziót kelti, hogy az összes alkalmazás egyszerre fut. A valóságban a legtöbbjük Suspended-ben van befagyasztva. A Suspended-ből való forró indítás sokszor gyorsabb, mint a Not Running-ból való hideg indítás, mivel a kód már be van töltve a memóriába.

Hogyan kezeli a rendszer a Suspended-et

Az iOS nyomon követi az összes alkalmazás állapotát, és a rendelkezésre álló memória alapján dönt a Suspended alkalmazások kiürítéséről. Memóriahiány esetén a rendszer elkezdi kiüríteni a Suspended alkalmazásokat, kezdve azokkal, amelyek a leghosszabb ideje vannak ebben az állapotban. Ha a memória továbbra is elégtelen, a rendszer áthelyezi az alkalmazásokat a Background-ból és az Inactive-ből Suspended-be, majd kiüríti őket. Ez a folyamat teljesen átlátható a felhasználó számára — ő csak az alkalmazás ikonját látja az App Switcher-ben, amelyre kattintva egy hideg indítás indul.

JellemzőSuspended (iOS)Background (iOS)Background (Android)
Kód futNemIgen (korlátozott)Igen (korlátozott)
MemóriábanIgenIgenIgen
CPU-fogyasztás0%AlacsonyAlacsony
Forró indításIgen — azonnali helyreállításIgen — Inactive-en keresztülNem — a folyamat lehet, hogy meg lett ölve
IdőtúllépésNem — órákig lehet a memóriában~30 másodperc (beginBackgroundTask után)API-verziótól függ
Rendszer általi kiürítésMemóriahiány eseténKritikus memóriahiány eseténLMK (Low Memory Killer)
Visszatérés munkáhozApp Switcher-ből — azonnalApp Switcher-ből — Inactive-en keresztülHideg indítás
State RestorationAjánlottNem szükségesSavedStateHandle

Suspended iOS-ben: a befagyasztás mechanizmusa

iOS-ben a Suspended automatikusan elérhetővé válik az összes háttérfeladat befejezése után. A rendszer meghívja az applicationDidEnterBackground-ot, időt ad a beginBackgroundTask végrehajtására (körülbelül 30 másodperc), majd erőszakosan felfüggeszti az összes szálat, és átviszi az alkalmazást a Suspended állapotba. A memóriában lévő objektumok megmaradnak, de semmilyen kód nem fut — az alkalmazás az aktuális állapotban van befagyasztva.

Kritikusan fontos pillanat: az applicationDidEnterBackground — az utolsó metódus, amely garantáltan meghívódik a Suspended előtt. Ezután az alkalmazás nem kap semmilyen értesítést a memóriából való kiürítésről. Ha a felhasználó vagy a rendszer megöli a Suspended állapotban lévő alkalmazást, sem az applicationWillTerminate, sem az applicationDidEnterBackground nem hívódik meg újra. Ezért minden adatmentésnek az applicationDidEnterBackground-ben kell történnie, nem az applicationWillTerminate-ben.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // Utolsó garantált hívás a Suspended előtt
    func applicationDidEnterBackground(_ application: UIApplication) {
        // Elmentünk mindent, aminek túl kell élnie a memóriából való kiürítést
        savePersistentState()
        saveNavigationStack()

        // További időt kérünk, ha szükséges
        let task = application.beginBackgroundTask {
            application.endBackgroundTask(task)
        }
    }

    // Visszatérés a Suspended-ből — forró indítás
    func applicationWillEnterForeground(_ application: UIApplication) {
        // Az alkalmazás Suspended-ben volt, visszatérünk a munkához
        print("Visszatérés Suspended-ből vagy Background-ból")
    }

    // Teljes helyreállítás a memóriából való kiürítés után
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Ha ez a kiürítés utáni hideg indítás a Suspended-ből —
        // visszaállítjuk a state restoration-t
        return true
    }

    private func savePersistentState() {
        UserDefaults.standard.set(Date(), forKey: "lastActiveDate")
    }

    private func saveNavigationStack() {
        guard let rootVC = window?.rootViewController else { return }
        // Elmentjük az aktuális navigációs vermet
        if let navController = rootVC as? UINavigationController {
            let vcClasses = navController.viewControllers.map { type(of: $0) }
            UserDefaults.standard.set(vcClasses.map { NSStringFromClass($0) }, forKey: "navStack")
        }
    }
}

A kód a Suspended kritikus kezelését mutatja iOS-ben. applicationDidEnterBackground — az utolsó garantált hívás. Minden adatmentésnek itt kell történnie: felhasználói állapot, navigációs verem, piszkozatok, időzítők. Az applicationWillEnterForeground a Suspended-ből vagy Background-ból való visszatéréskor hívódik meg. A didFinishLaunchingWithOptions — csak hideg indításkor, amikor az alkalmazás ki lett ürítve a memóriából a Suspended után.

Suspended Androidban — létezik analóg

Androidban nincs közvetlen analógja az iOS Suspended-nek. Az Android nem fagyasztja be az alkalmazásokat a memóriában a végrehajtási kontextus megőrzésével. Ehelyett az Android vagy a háttérben tartja a folyamatot (Background), vagy befejezi azt (Not Running). Azonban Android 11+ (API 30) készülékeken megjelent az App Freezer mechanizmus, amely a SIGSTOP jel segítségével felfüggeszti a háttérfolyamatok végrehajtását. Ez a Suspended funkcionális analógja, de fontos különbségekkel.

App Freezer — az Android memóriakezelő rendszerének része. Amikor egy alkalmazás hosszú ideig a háttérben van, és nincs aktív értesítése, a rendszer SIGSTOP-ot küld neki, felfüggesztve az összes szálat. Amikor az alkalmazás visszatér az előtérbe, SIGCONT kerül elküldésre, és a végrehajtás folytatódik. Fő különbség az iOS-hez képest: az App Freezer nem garantálja az állapot megőrzését — a memóriában lévő adatok elveszhetnek, ha a folyamatot megölik a befagyasztás során.

Androidban ajánlott a SavedStateHandle használata a ViewModel-ben az állapot automatikus mentéséhez bármilyen folyamatbefejezéskor. A SavedStateHandle adatokat ment a Bundle-be az onSaveInstanceState-n keresztül, amely túléli mind az App Freezer-t, mind a Process Death-t. Az iOS-szel ellentétben, ahol a Suspended-ből való kiürítés kivételes helyzet, Androidban a Process Death normális viselkedés, amelyet mindig várni kell.

kotlin
// SavedStateHandle — menekülés a Process Death elől Androidban
class CheckoutViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    // Állapot, amely túléli a folyamatot még az App Freezer után is
    var currentStep: MutableLiveData<Int> =
        savedStateHandle.getLiveData("checkout_step", 1)

    var cartItems: MutableLiveData<List<CartItem>> =
        savedStateHandle.getLiveData("cart_items", emptyList())

    fun proceedToNextStep() {
        currentStep.value = (currentStep.value ?: 0) + 1
    }

    fun addToCart(item: CartItem) {
        val updatedList = (cartItems.value ?: emptyList()) + item
        cartItems.value = updatedList
        savedStateHandle["cart_items"] = updatedList
    }
}

// Mentés onStop-ban App Freezer esetére
class MainActivity : AppCompatActivity() {

    override fun onStop() {
        super.onStop()
        // Elmentjük az adatokat, amelyeknek túl kell élniük a befagyasztást
        saveDraftData()
        // Felszabadítjuk az erőforrásokat, amelyek nem kellenek befagyasztott állapotban
        releaseHeavyResources()
        // Figyelmeztetjük, hogy az alkalmazás be lesz fagyasztva
        // (Naplózás hibakereséshez)
        Log.d("Lifecycle", "Activity leállítva — lehetséges App Freeze")
    }
}

A kód a Suspended analóg kezelésének megközelítését mutatja Androidban. SavedStateHandle a ViewModel-ben automatikusan menti és visszaállítja az adatokat Process Death esetén. onStop — az utolsó garantált esemény a lehetséges App Freezer vagy folyamatbefejezés előtt. A megrendelő űrlap állapota, a kosárban lévő termékek listája — mindezek az adatok túlélik a befagyasztást a SavedStateHandle-nek köszönhetően. Nehéz erőforrásokhoz (bitképek, adatbázis-kurzorok) az onStop a memória felszabadításának helye.

State Restoration: helyreállítás Suspended után

State Restoration — az iOS beépített mechanizmusa a UI-állapot mentésére és helyreállítására az alkalmazás memóriából való kiürítése után. Ha az alkalmazás Suspended-ben volt, és a rendszer kiürítette, a következő hideg indításkor a state restoration visszaállítja a navigációs vermet, a görgetési pozíciót, az űrlapok állapotát és más UI-elemeket. A felhasználó ugyanarra a képernyőre tér vissza, ahol abbahagyta.

A State Restoration a UIViewControllerRestoration és UIStateRestoring protokollokon keresztül működik. A fejlesztő restorationIdentifier-t rendel minden ViewController-hez és View-hoz, amelyet helyre szeretne állítani. A Background-ba lépéskor az iOS kódolja ezen objektumok állapotát. A kiürítésből való visszatérés után az iOS új objektumokat hoz létre, és dekódolja a mentett állapotot. State Restoration nélkül a felhasználó üres képernyőt fog látni a hideg indítás után ahelyett, ahol abbahagyta.

swift
import UIKit

class DetailViewController: UIViewController {

    var itemID: String = ""
    var scrollPosition: CGPoint = .zero

    override func viewDidLoad() {
        super.viewDidLoad()
        restorationIdentifier = "DetailViewController"
        restorationClass = type(of: self)
    }

    override func encodeRestorableState(with coder: NSCoder) {
        super.encodeRestorableState(with: coder)
        coder.encode(itemID, forKey: "itemID")
        coder.encode(scrollPosition, forKey: "scrollPosition")
    }

    override func decodeRestorableState(with coder: NSCoder) {
        super.decodeRestorableState(with: coder)
        if let savedID = coder.decodeObject(forKey: "itemID") as? String {
            itemID = savedID
            loadItem()
        }
        if let savedPosition = coder.decodeCGPoint(forKey: "scrollPosition") {
            scrollPosition = savedPosition
            // Helyreállítjuk a pozíciót az adatok betöltése után
        }
    }
}

// AppDelegate — a State Restoration aktiválása
func application(
    _ application: UIApplication,
    shouldSaveSecureApplicationState coder: NSCoder
) -> Bool {
    return true
}

func application(
    _ application: UIApplication,
    shouldRestoreSecureApplicationState coder: NSCoder
) -> Bool {
    return true
}

A kód a State Restoration megvalósítását mutatja iOS-ben. restorationIdentifier és restorationClass szükséges minden helyreállítandó ViewController-hez. Az encodeRestorableState/decodeRestorableState az NSCoder-en keresztül menti és tölti be az adatokat. Az AppDelegate-ben a shouldSaveSecureApplicationState és a shouldRestoreSecureApplicationState bekapcsolja az állapot titkosított mentését. iOS 12+ óta ajánlott a secure encoding (NSSecureCoding) használata az adatok védelmére.

Legjobb gyakorlatok a Suspended-del való munkához

Első szabály — soha ne számíts arra, hogy az alkalmazás visszatér a Suspended-ből. A rendszer bármikor kiürítheti az alkalmazást. Az összes kritikusan fontos adatot a Suspended-be való átlépés előtt — vagyis az applicationDidEnterBackground-ben vagy onStop-ban — tartós tárhelyre kell menteni. UserDefaults, Core Data, File Manager — megfelelő tárolók. A memória (változók, tulajdonságok) — megbízhatatlan tároló azoknak az adatoknak, amelyeknek túl kell élniük a Suspended-et.

Második szabály — szabadítsd fel az erőforrásokat a Suspended előtt. Zárd be a fájlleírókat, szabadítsd fel a GPU memóriát (Metal, Core Graphics), zárd be a hálózati kapcsolatokat. Bár az alkalmazás nem fogyaszt CPU-t Suspended-ben, a lefoglalt erőforrások blokkolva vannak más alkalmazások számára. iOS-ben Suspended-ben nem lehet nyitott socketeket tartani — a Suspended-ből való visszatéréskor ezek működésképtelenek lehetnek, ami hibákat okoz.

Harmadik szabály — ne helyezz időfüggő logikát a Suspended-ből való visszatérésre várva. Az időzítők, callback-ek és hálózati tevékenység leállnak Suspended-ben. Ha az alkalmazás több órát volt Suspended-ben, a visszatéréskor az időzítő helytelenül működhet. Ellenőrizd az adatok aktualitását visszatéréskor — lehet, hogy a gyorsítótár elavult, és az engedélyezési token lejárt.

Negyedik szabály — használd a State Restoration-t az összes képernyőhöz, különösen a beviteli űrlapokhoz, görgethető listákhoz és részletképernyőkhöz. State Restoration nélkül a felhasználó a kiürített Suspended-ből való visszatérés után az alkalmazás kezdőképernyőjét fogja látni ahelyett, ahol abbahagyta. Ez rontja a felhasználói élményt és a felhasználót a műveletek megismétlésére kényszeríti.

swift
import UIKit

// Ellenőrzés: ki lett-e ürítve az alkalmazás a memóriából?
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    // Ellenőrizzük, hogy létezik-e mentett állapot
    if UserDefaults.standard.object(forKey: "navStack") != nil {
        // Az alkalmazás ki lett ürítve a Suspended-ből
        // Vissza kell állítani az állapotot
        restoreNavigationStack()
    } else {
        // Tiszta hideg indítás a Not Running-ból
        showOnboardingIfNeeded()
    }
    return true
}

private func restoreNavigationStack() {
    guard let savedStack = UserDefaults.standard.array(forKey: "navStack") as? [String],
          let navController = window?.rootViewController as? UINavigationController
    else { return }

    for vcClassName in savedStack {
        if let vcClass = NSClassFromString(vcClassName) as? UIViewController.Type {
            let vc = vcClass.init()
            navController.pushViewController(vc, animated: false)
        }
    }
}

A kód azt a gyakorlatot mutatja, hogyan lehet meghatározni, hogy az alkalmazás ki lett-e ürítve a Suspended-ből. A UserDefaults ellenőrzése a mentett navigációs verem meglétére lehetővé teszi a kiürítés utáni hideg indítás megkülönböztetését a tiszta hideg indítástól. Az első esetben a navigációs verem helyreáll, a másodikban az onboarding vagy a főképernyő jelenik meg. Ez a megközelítés kiegészíti a beépített State Restoration-t azokban az esetekben, amikor az NSCoder nem elegendő.

Gyakran Ismételt Kérdések

Mennyi ideig maradhat egy alkalmazás Suspended-ben?

Korlátlan — néhány másodperctől néhány napig. Az iOS-nek nincs időtúllépése a Suspended számára. Az alkalmazás addig marad a memóriában, amíg a rendszer úgy nem dönt, hogy kiüríti az erőforráshiány miatt. A gyakorlatban az alkalmazások 15 perctől néhány óráig maradnak Suspended-ben, a készülék RAM-jának méretétől és az aktív alkalmazások számától függően.

Meghívódik-e az applicationWillTerminate a Suspended-ből való kiürítéskor?

Nem. Az applicationWillTerminate nem hívódik meg az alkalmazás Suspended-ből való kiürítésekor. A rendszer egyszerűen felszabadítja a memóriát anélkül, hogy értesítené az alkalmazást. Ez egy újabb ok, amiért minden adatmentésnek az applicationDidEnterBackground-ben kell történnie. Az applicationWillTerminate csak akkor hívódik meg, amikor a felhasználó manuálisan befejezi az alkalmazást az App Switcher-ből való elhúzással.

Van az Androidnak Suspended analógja?

Nincs közvetlen analóg. Android 11+ készülékeken megjelent az App Freezer, amely SIGSTOP-on keresztül függeszti fel a háttérfolyamatokat — ez funkcionálisan hasonlít a Suspended-hez. Az Android-alkalmazásokat azonban úgy kell tervezni, hogy bármikor számítsanak Process Death-re. Használd a SavedStateHandle-t a ViewModel-ben és az onSaveInstanceState-t az állapot mentésére, amely túléli mind az App Freezer-t, mind a Process Death-t.

Hogyan ellenőrizhető, hogy az alkalmazás Suspended-ben volt?

iOS-ben nincs közvetlen API az ellenőrzésre. Közvetett módszer: ellenőrizd a UserDefaults-ot a mentett állapot meglétére a didFinishLaunchingWithOptions-ben. Ha az állapot létezik — az alkalmazás ki lett ürítve a Suspended-ből, és hideg indítást végez. Ha nincs állapot — tiszta hideg indítás. SwiftUI-ben elmenthetsz egy flag-et a scenePhase.background-ban, és ellenőrizheted a következő indításkor.

Mi az a snapshot a Suspended kontextusában?

A Suspended-be való átlépéskor az iOS készít egy snapshot-ot — az alkalmazás aktuális UI-jának képernyőképét. Ez a kép az App Switcher-ben és az alkalmazásba való visszatéréskor (olvadási animációként) jelenik meg. Ha az alkalmazás bizalmas adatokat tartalmaz, a snapshot felfedheti azokat. Védelemhez használd az UIApplication.shouldSnapshotSecureApp (iOS 16+) tulajdonságot, vagy alkalmazz blur-overlay-t az applicationDidEnterBackground-ben.

Összefoglalás

  • Suspended — alkalmazás le van fagyasztva az iOS memóriában, kód nem fut, de a UI-verem megmarad az azonnali helyreállításhoz
  • iOS egyedisége — a Suspended nem létezik Androidban; az Android az App Freezer-t (SIGSTOP) használja részleges analógként
  • Kiürítés — a rendszer a Suspended alkalmazásokat üríti ki elsőként memóriahiány esetén, értesítés nélkül
  • Mentés — applicationDidEnterBackground — az utolsó garantált metódus, minden adatot itt kell menteni
  • State Restoration — NSCoder mechanizmus a UI automatikus helyreállításához a Suspended-ből való kiürítés után
  • Android alternatíva — SavedStateHandle + onSaveInstanceState a Process Death túléléséhez
  • Snapshot — iOS képernyőképet készít Suspended-kor; a bizalmas adatokat blur-overlay-jel vagy secure snapshot segítségével kell elrejteni

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is