如何将我的 SwiftUI 视图的 @State 交换为我的视图模型 @Published 变量?

Posted

技术标签:

【中文标题】如何将我的 SwiftUI 视图的 @State 交换为我的视图模型 @Published 变量?【英文标题】:How to swap my @State of my SwiftUI view for my view model @Published variable? 【发布时间】:2020-05-10 18:08:30 【问题描述】:

我有一个按钮可以触发我的视图状态。由于我现在添加了一个网络调用,我希望我的视图模型将 @State 替换为其 @Publihed 变量以执行相同的更改。

如何使用我的@Published 代替我的@State 变量?

这是我的 SwiftUI 视图:

struct ContentView: View 

  @ObservedObject var viewModel = OnboardingViewModel()

  // This is the value I want to use as @Publisher
  @State var isLoggedIn = false

  var body: some View 
    ZStack 
      Button(action: 
        // Before my @State was here
        // self.isLoggedIn = true
        self.viewModel.login()
      ) 
        Text("Log in")
      

      if isLoggedIn 
        TutorialView()
      
    
  

这是我的模型:

final class OnboardingViewModel: ObservableObject 

  @Published var isLoggedIn = false

  private var subscriptions = Set<AnyCancellable>()

  func demoLogin() 
    AuthRequest.shared.login()
      .sink(
        receiveCompletion:  print($0) ,
        receiveValue: 
          // My credentials
          print("Login: \($0.login)\nToken: \($0.token)")
          DispatchQueue.main.async 
            // Once I am logged in, I want this
            // value to change my view.
            self.isLoggedIn = true  )
      .store(in: &subscriptions)
  

【问题讨论】:

【参考方案1】:

移除状态,直接使用视图模型成员,如下

struct ContentView: View 

  @ObservedObject var viewModel = OnboardingViewModel()

  var body: some View 
    ZStack 
      Button(action: 
        self.viewModel.demoLogin()
      ) 
        Text("Log in")
      

      if viewModel.isLoggedIn     // << here !!
        TutorialView()
      
    
  

【讨论】:

这是我一开始做的,但它不起作用。 @Published 似乎没有将真实值发送到这个“if 语句”。 @RolandLariotte,究竟是什么不起作用?您是否看到控制台登录从视图模型接收值? 不起作用的是我看不到我的 TutorialView(),因为它仍然被“if viewModel.isLoggedIn ”隐藏。当我按照您的建议进行打印时,该值仍然是错误的。当从 DispatchQueue 中取出“self.isLoggedIn = true”时,该值在控制台中变为 true,但不会对视图进行任何更改。 @RolandLariotte,这是唯一的代码还是一些简化版本?提供的代码是OnboardingViewModel() 创建的唯一地方吗? @RolandLariotte,然后检查 *that another view" 使用相同的 OnboardingViewModel 实例,因为我现在确定它没有。【参考方案2】:

嘿,Roland,我认为您正在寻找的是:

$viewMode.isLoggedIn

在 var 之前添加 $ 将确保 SwiftUI 知道它的值变化。

struct ContentView: View 

  @ObservedObject var viewModel = OnboardingViewModel()

  var body: some View 
    ZStack 
      Button(action: 
        viewModel.login()
      ) 
        Text("Log in")
      

      if $viewMode.isLoggedIn 
        TutorialView()
      
    
  




class OnboardingViewModel: ObservableObject 

    @Published var isLoggedIn = false

    
    func login() 
       isLoggedIn = true
    

【讨论】:

以上是关于如何将我的 SwiftUI 视图的 @State 交换为我的视图模型 @Published 变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SwiftUI 将我的按钮粘贴到视图底部?

基于 State int 的 SwiftUI ForEach

为 Swiftui 视图转换 @State 的计算属性

如何根据 SwiftUI 中的 @State 更改导航视图的导航视图样式?

SwiftUI:如何在函数计算 @State 值时同时更新视图?

为啥我的 SwiftUI 视图不会在更新 @State var 时更新?