gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 17:23:43 24 4
gpt4 key购买 nike

我想在我的应用程序第一次启动时加载一些数据,当应用程序是 时前景化 我想确保我有最新的数据。
状态存储在 ViewModel 类中,我的 View 拥有该类作为 @StateObject .我读了 ScenePhase来自环境,并在 onChange(of: scenePhase) ,如果需要,我会在我的 ViewModel 上调用一个方法来开始重新加载。
但是我应该什么时候开始初始加载?

  • ContentView.init太早了,因为scenePhase.background .即使是 .active ,我显然不应该从 init 访问 StateObject — SwiftUI 会记录运行时警告。
  • ViewModel.init也太早了——理论上,我认为即使应用程序从未出现在前台,也可以创建 View 模型。
  • 第一次var body被访问,scenePhase为.active . onChange(of:)不会为其初始值调用闭包,因此在我后台和重新前台应用程序之前,它永远不会被调用。
  • class ViewModel: ObservableObject {
    init() {
    // 1. reload() here? Could happen without the app entering the foreground.
    }

    func reload() { ... }
    }


    struct ContentView: View {
    @Environment(\.scenePhase) var scenePhase
    @StateObject var viewModel = ViewModel()

    init() {
    // 2. viewModel.reload() here?
    // - problem 1: scenePhase == .background, not .active
    // - problem 2: not supposed to access a @StateObject here anyway
    }

    var body: some View {
    (...)
    // The initial render happens when scenePhase == .active,
    // so I don't get the onChange callback until it changes again.
    .onChange(of: scenePhase) {
    if $0 == .active {
    viewModel.reload()
    }
    }
    }
    }

    最佳答案

    如果您的 ContentView是您可以使用的根 View onAppear .

    但是,如果您的 ContentView可以消失然后重新出现上述解决方法不起作用。
    一个可能的解决方案可能是将一个变量注入(inject)到环境中:

    struct LaunchAppKey: EnvironmentKey {
    static let defaultValue = Binding.constant(false)
    }

    extension EnvironmentValues {
    var isAppLaunched: Binding<Bool> {
    get { return self[LaunchAppKey] }
    set { self[LaunchAppKey] = newValue }
    }
    }
    @main
    struct TestApp: App {
    @State private var isAppLaunched = false
    @State private var showContentView = true

    var body: some Scene {
    WindowGroup {
    VStack {
    if showContentView {
    ContentView()
    } else {
    Text("Some other view")
    }
    }
    .environment(\.isAppLaunched, $isAppLaunched)
    .onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    showContentView.toggle()
    }
    DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
    showContentView.toggle()
    }
    }
    }
    }
    }
    struct ContentView: View {
    @Environment(\.isAppLaunched) var isAppLaunched

    var body: some View {
    (...)
    .onAppear {
    guard !isAppLaunched.wrappedValue else { return }
    isAppLaunched.wrappedValue = true
    print("apppear")
    }
    }
    }

    关于swiftui - 在第一个 onChange(of :)?) 之前,我在哪里处理初始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64707912/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com