我在哪里处理第一个 onChange(of:) 之前的初始值?

jtb*_*des 5 swiftui

我想在我的应用程序首次启动时加载一些数据,并且当应用程序处于前台时我想确保我拥有最新的数据。

\n

状态存储在 ViewModel 类中,我的视图将其作为@StateObject. ScenePhase我从环境中读取了,并在 中onChange(of: scenePhase)调用了 ViewModel 上的一个方法来根据需要启动重新加载。

\n

但是我应该什么时候开始初始加载呢?

\n
    \n
  • ContentView.init还太早了,因为scenePhase.background。即使是.active,我显然也不应该从 init \xe2\x80\x94 SwiftUI 记录运行时警告来访问 StateObject。
  • \n
  • ViewModel.init理论上来说还太早 \xe2\x80\x94 ,我认为即使应用程序从未被带到前台,也可以创建视图模型。
  • \n
  • 第一次var body访问,scenePhase为.activeonChange(of:)不会调用闭包的初始值,因此在我将应用程序置于后台并重新前台之前,它永远不会被调用。
  • \n
\n
class ViewModel: ObservableObject {\n  init() {\n    // 1. reload() here? Could happen without the app entering the foreground.\n  }\n\n  func reload() { ... }\n}\n\n\nstruct ContentView: View {\n  @Environment(\\.scenePhase) var scenePhase\n  @StateObject var viewModel = ViewModel()\n\n  init() {\n    // 2. viewModel.reload() here?\n    //  - problem 1: scenePhase == .background, not .active\n    //  - problem 2: not supposed to access a @StateObject here anyway\n  }\n\n  var body: some View {\n    (...)\n      // The initial render happens when scenePhase == .active,\n      // so I don't get the onChange callback until it changes again.\n      .onChange(of: scenePhase) {\n        if $0 == .active {\n          viewModel.reload()\n        }\n      }\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Gra*_*ipe 2

从 iOS 17.0+、macOS 14.0+ 等版本开始,新增了onChange支持初始参数的功能。

onchange(of:initial:_:)

.onChange(of: focusState, initial: true) { (oldState, newState) in
    // Will run when the view appears
}
Run Code Online (Sandbox Code Playgroud)