如何在 SwiftUI 中将视图属性绑定到 ViewModel 属性

时间:2021-03-23 11:55:26

标签: swift swiftui

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

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

在重置密码的异步操作之后,我想关闭重置密码视图并返回到 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 很陌生,不确定我是否以正确的方式思考这个问题。

1 个答案:

答案 0 :(得分:1)

您已正确绑定 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")
    })
  }
}