为啥我的@ObservedObject 没有在我的视图中执行更改?

Posted

技术标签:

【中文标题】为啥我的@ObservedObject 没有在我的视图中执行更改?【英文标题】: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)
     
    
  

【问题讨论】:

【参考方案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。

以上是关于为啥我的@ObservedObject 没有在我的视图中执行更改?的主要内容,如果未能解决你的问题,请参考以下文章

无法在真实 iPhone 上使用 @ObservedObject

为啥 SwiftUI ObservedObject 不能在列表行中工作?

SwiftUI:为啥 ObservedObject 在 AppDelegate 中不起作用?

为啥我的 Listview 没有在我的活动中显示任何内容?

为啥在我的 java 代码中没有调用通知

为啥我的分段控件没有显示在我的视图中?