0

我有一个简单的加载器,它在 @Publisher 设置为 true 时执行加载动画。发出网络请求时,此发布者在 ViewModel 上设置为 true。我希望这个值能改变我的看法,但事实并非如此。显示的 ContentView 更复杂,其中包含许多视图,但它是所有视图的根视图。加载程序是一个 Lottie 视图,当手动将所有内容设置为 true 时,它​​可以完美运行。Loader 是一个独立的 @ObservableObject,因为我想在许多其他 ViewModel 中使用它。

为什么@ObservedObject var loader从 ViewModel 设置时我的视图状态没有执行任何更改?

我的装载机:

final class Loader: ObservableObject {
  @Published var isLoading = false
}

我触发加载器的视图模型:(在控制台中,加载器的值正在相应地改变)

final class OnboardingViewModel: ObservableObject {

  @ObservedObject var loader = Loader()

  func demoLogin() {
    loaderIsLoading(true)  // loader set to true
    AuthRequest.shared
      .demoLogin()
      .sink(
        receiveCompletion: {
          self.loaderIsLoading(false) }, // loader set to false
        receiveValue: {
          self.enterDemoAction()
          print("Login: \($0.login)\nToken: \($0.token)") })
      .store(in: &subscriptions)
  }

  func loaderIsLoading(_ action: Bool) {
    DispatchQueue.main.async {
      self.loader.isLoading = action
    }
  }
}

这是我希望魔法发生的 SwiftUI 视图:(它比这要复杂得多,子视图和组件在彼此内部)

struct ContentView: View {

  @EnvironmentObject var onboardingViewModel: OnboardingViewModel

  @ObservedObject var loader = Loader()

  var body: some View {
    ZStack {
    if loader.isLoading {  // this is where it is not updated
      LottieView(named: .loading,
                 loop: loader.isLoading,
                 width: 220, height: 220)
     }
    }
  }
}
4

1 回答 1

1

@ObservedObject是视图的一种模式,它在外面没有意义,即。在这种情况下,在模型中。

这是提供代码的可能解决方案。

1) 在模型中

final class OnboardingViewModel: ObservableObject {
  var loader = Loader() // << just property

  // ... other code

2) 在视图中

struct ContentView: View {

  @EnvironmentObject var onboardingViewModel: OnboardingViewModel

  var body: some View {
     InnerView(loader: onboardingViewModel.loader)  // << pass from Env
  }

  struct InnerView: View {
     @ObservedObject var loader: Loader

     var body: some View {
         ZStack {
            if loader.isLoading {  // this is where it is not updated
               LottieView(named: .loading,
                 loop: loader.isLoading,
                 width: 220, height: 220)
            }
         }
     }
  }
}

注意:我看不到你在哪里调用onboardingViewModel.demoLogin(),但我希望它在某处被激活,因为我看到它是唯一激活的函数Loader

于 2020-05-11T14:43:52.987 回答