SwiftUI

2024 年 1 月 21 日

SwiftUI 用來監聽生命週期的 ScenePhase

已複製到剪貼板


ScenePhase 可以用來監聽視窗正被操作的狀態。

SwiftUI
SwiftUI

SwiftUI ScenePhase 概覽

在使用者操作 App 的過程中,可能會使用到一半就滑掉,去使用別的 App,然後一下子又回來。在這樣的情境下,系統會將 App 的 Scene 在不同的階段之間做切換,而我們就能在這樣的生命週期轉變時,去做對應的事。

讀取 ScenePhase

在 SwiftUI 中,要讀取 ScenePhase 非常簡單!可以直接用 @Environment 拿到環境變數:

@Environment(\.scenePhase) private var scenePhase

注意

不過 scenePhase 這個環境變數的意義,會因為我們取值的地方不同而有不同,主要可以分成以下三種:在 View 裡、在 App 裡、在 Scene 裡。

在 View 裡讀取 ScenePhase

如果我們在某個 View 裡讀取 scenePhase 時,拿到的會是有著這個 View 的 Scene 的狀態。例如:我們可以在一個 View 不在前景時就停止計時器,而回到前景後再繼續計時:

struct Example: View {
  
    @ObservedObject var model: DataModel
    @Environment(\.scenePhase) private var scenePhase

    var body: some View {
        TimerView()
            .onChange(of: scenePhase) { phase in
                model.isTimerRunning = (phase == .active)
            }
    }
}

在 App 裡讀取 ScenePhase

如果我們直接在 App 下讀取 scenePhase 的話,就會拿到整個 App 的狀態。只要有 App 的任何一個 Scene 處在前景的話,scenePhase 就會是 active,而沒有任何一個 Scene 在前景時,scenePhase 就會是 inactive。

SwiftUI ScenePhase.background

background 是 ScenePhase 除了 active 與 inactive 以外的第三個狀態,這是個特別的狀態,代表著 App 再過不久就會被結束掉,而進到這個狀態也是給我們最後的機會去清掉我們該清的資源。

@main
struct Example: App {

    @Environment(\.scenePhase) private var scenePhase

    var body: some Scene {
        WindowGroup {
            MyRootView()
        }
        .onChange(of: scenePhase) { phase in
            if phase == .background {
                // 當 App 的所有 Scene 都進到 background 時
                // 可以執行必要的資源清理
            }
        }
    }
}

在 Scene 裡讀取 ScenePhase

當我們在客製的 Scene 裡讀取 scenePhase 時,會拿到組成這個 Scene 的所有 Scene 的狀態,有 Scene 在前景的話,就是 active,都不在前景的話,就是 inactive。

struct Example: Scene {

    @Environment(\.scenePhase) private var scenePhase

    var body: some Scene {
        WindowGroup {
            MyRootView()
        }
        
        WindowGroup {
            AnotherView()
        }
        .onChange(of: scenePhase) { phase in
            if phase == .background {
                // 當所有 Scene 都進到 background 時
                // 可以執行必要的資源清理
            }
        }
    }
}

分享文章

已複製到剪貼板

主題文章

查看 SwiftUI

超級感謝

關於 XcodeProject

XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。


Contacts

Ricky Chuang

XcodeProject

RickyChuang.xcodeproj@gmail.com

XcodeProject 聯絡

contact.xcodeproj@gmail.com

最新文章