【问题标题】:SwiftUI MVVM how to set callback from ViewModel function to ViewSwiftUI MVVM 如何设置从 ViewModel 函数到 View 的回调
【发布时间】:2021-01-25 04:59:27
【问题描述】:

我正在使用 MVVM 设置登录页面逻辑,但在从 ViewModel 调用该函数后,我无法弄清楚如何修改用户登录状态。

登录查看

struct LoginView: View {
    @ObservedObject var user: User
    @ObservedObject var viewModel = LoginViewModel()
    @State var inputUser: String = ""
    @State var inputPass: String = ""
    
    var body: some View {
        ScrollView {
            VStack(alignment: .leading) {
                Group {
                    Text("Login")
                    CustomTextField(placeHolder: "Username", value: $viewModel.user, secure: false)
                    CustomTextField(placeHolder: "Password", value: $viewModel.pass, secure: true)
                    Button(action: {
                        self.viewModel.login()
                        // After this login function completes and if return result success
                        // How do I pass data / callback after login?
                        // How to check if login success then set token or login failed
                        self.user.tokenIsActive = true
                    }) {
                        Text("Sign In")
                    }
                }
            }
        }
    }
}

登录视图模型

class LoginViewModel: ObservableObject, LoginService {
    var apiSession: APIService
    
    @Published var user = ""
    @Published var pass = ""
    
    @Published var accessToken: String?
    
    var cancellables = Set<AnyCancellable>()
    
    init(apiSession: APIService = APISession()) {
        self.apiSession = apiSession
    }
    
    func login() {
        let cancellable = self.loginUser(user: user, pass: pass)
            .sink(receiveCompletion: { result in
                switch result {
                case .failure(let error):
                    print("Handle error: \(error)")
                case .finished:
                    break
                }
                
            }) { (result) in
                self.accessToken = result.accessToken
                UserDefaults.standard.set(self.accessToken, forKey: "accessToken")
        }
        cancellables.insert(cancellable)
    }
}

用户

所以我将用户会话存储在 User 类中

class User: ObservableObject {
    @Published var tokenIsActive = false;
}

如何从视图模型中的登录功能传递数据并检查登录是否成功并设置用户令牌?提前谢谢你。

【问题讨论】:

  • 为什么你的视图中有 User 作为属性,不应该通过视图模型来访问吗?

标签: swift mvvm swiftui


【解决方案1】:

使用完成块并更新您的状态。

func login(_ completion: @escaping ((Bool)->Void)) {
    let cancellable = self.loginUser(user: user, pass: pass)
        .sink(receiveCompletion: { result in
            switch result {
            case .failure(let error):
                print("Handle error: \(error)")
            case .finished:
                break
            }
            
        }) { (result) in
            completion(true)
            self.accessToken = result.accessToken
            UserDefaults.standard.set(self.accessToken, forKey: "accessToken")
    }
    cancellables.insert(cancellable)
}

使用:

self.viewModel.login { (isSuccess) in
    if isSuccess {
        self.user.tokenIsActive = true
    }
}

【讨论】:

  • 感谢您的回答,抱歉刚刚有时间回复。这确实解决了它!您能否详细说明一下代码的作用“func login(_ completion: @escaping ((Bool)->Void)) {”以及什么是“completion(true)”,对不起,我对 Swift 很陌生,或者如果您可以提供阅读参考,它可能会极大地帮助其他人更多地了解 Swift。非常感谢!
  • 这是一个完成闭包。当您必须处理异步进程时使用它。 medium.com/@dhavalkansara51/…
  • 非常感谢伙计!很好的阅读,对 Swift 有更多的了解
  • 使用Combine的要点之一是不必使用完成/回调吗?
  • @JoakimDanielson 我不太了解 combine,但我们可以使用 Future?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 2012-09-02
相关资源
最近更新 更多