【问题标题】:Why is my @ObservedObject not performing changes in my view?为什么我的@ObservedObject 没有在我的视图中执行更改?
【发布时间】:2020-05-11 14:28:42
【问题描述】:

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

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

我的装载机:

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

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

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)
     }
    }
  }
}

【问题讨论】:

    标签: swiftui combine observableobject


    【解决方案1】:

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

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

    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 的函数。

    【讨论】:

    • 效果很好,但是只有 OnboardingViewModel 可以触发这个加载器,因为它是这样调用的 InnerView(loader: onboardingViewModel.loader)。但我想使用 Loader: ObservableObject 和许多 ViewModel。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    相关资源
    最近更新 更多