首页 > 解决方案 > 如何在 SwiftUI 中将视图属性绑定到 ViewModel 属性

问题描述

我无法弄清楚如何关闭在 SwiftUI 中全屏显示的视图。

在登录页面上,点击重置密码选项。当用户点击那里时,会出现另一个视图。新视图的 ViewModel 与 SignInView 的不同。

在异步操作重置密码后,我想关闭重置密码视图并返回 SignInView。缩写版本如下所示:

// SignInView

@State var isActive = false

var body: some View {
    Text("Forgot Password?  Tap to reset")
        .onTapGesture {
            isActive = true
        }
        .fullScreenCover(isPresented: $isActive, content: {
            ResetPasswordView(viewModel: ResetPasswordViewModel(), isActive: $isActive)
        })
}


// ResetPasswordView

@ObservedObject var viewModel: ResetPasswordViewModel

@Binding var isActive: Bool

init(viewModel: ResetPasswordViewModel, isActive: Binding<Bool>) {
    self.viewModel = viewModel
    self._isActive = isActive
}

var body: some View {
    Button(action: {
        viewModel.resetPassword()
    }, label: {
        Text("Done")
    })
}

因为异步密码重置操作发生在 ResetPasswordView 的 ViewModel 中,所以我希望能够在完成后将 isActive 设置为 false 并关闭 ResetPasswordView。但我不知道如何从 ViewModel 更改 isActive,因为它直接传递给视图。

我对 MVVM 很陌生,不确定我是否以正确的方式思考这个问题。

标签: swiftswiftui

解决方案


您已isActive正确绑定。现在您只需将其设置为false.
您只需要在适当的位置进行以下操作:

isActive = false

一种方法是直接让ViewModel手柄isActive

解决方案

class ResetPasswordViewModel: ObservableObject {
  @Binding var isActive: Bool

  //...other viewModel variables
  
  init(/*...your other params*/ isActive: Binding<Bool>) {
    self._isActive = isActive
  }
  
  func resetPassword() {
    //...your logic
    isActive = false
  }
}

示例(使用中):

struct ContentView: View {
  @State var isActive = false
  
  var body: some View {
    Text("Forgot Password?  Tap to reset")
      .onTapGesture { isActive = true }
      .fullScreenCover(isPresented: $isActive,
               content: {
                ResetPasswordView(viewModel: ResetPasswordViewModel(isActive: $isActive))
               })
  }
}

struct ResetPasswordView: View {
  @ObservedObject var viewModel: ResetPasswordViewModel
  
  var body: some View {
    Button(action: {
      viewModel.resetPassword()
    }, label: {
      Text("Done")
    })
  }
}

推荐阅读