【问题标题】:Can I use MVVM without data binding?我可以在没有数据绑定的情况下使用 MVVM 吗?
【发布时间】:2018-05-22 16:43:39
【问题描述】:

我正在尝试使用 MVVM。在阅读了一些关于 MVVM 的博客后,我发现它们使用了 Rx、KVO、Boxing 等数据绑定技术。以下是我使用 MVVM 验证用户的类。我没有为数据绑定添加任何代码。我所做的只是在单击提交按钮时将用户名和密码从视图控制器传递给我的视图模型类。视图模型包含验证的所有逻辑。最后,它将状态返回给视图控制器,具体取决于视图控制器显示的一些消息。我在徘徊这是要走的路还是应该使用一些数据绑定?

SignUpViewController.swift

import UIKit

class SignUpViewController: UIViewController {

    let signupviewmodel = SignUpViewModel()

    @IBOutlet weak var textFieldUsername: UITextField!
    @IBOutlet weak var textFieldPassword: UITextField!
    @IBOutlet weak var textFieldPasswordConfirm: UITextField!

    @IBAction func initialSignUp(_ sender: Any) {
        signupviewmodel.updateUsername(username: textFieldUsername.text!)
        signupviewmodel.updatePassword(password: textFieldPassword.text!)
        signupviewmodel.updateConfirmPassword(confirmpassword: textFieldPasswordConfirm.text!)

        switch signupviewmodel.validateUser() {
            case .Valid:
                showAlert(title: "Valid", message: "success") 
            case .InValid(let error):
                showAlert(title: "Error Validation", message: error)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func showAlert(title: String, message: String) -> Void {
        let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }
}

SignUpViewModel.swift

import Foundation

enum UserValidationState {
    case Valid
    case InValid(String)
}

class SignUpViewModel {
    private let minPasswordLength: Int = 6
    private var user = User()

    var username: String {
        return user.username!
    }

    var password: String {
        return user.password!
    }

    var confirmpassword: String {
        return user.confirmpassword!
    }
}

extension SignUpViewModel {

    func updateUsername(username: String) {
        user.username = username
    }

    func updatePassword(password: String) {
        user.password = password
    }

    func updateConfirmPassword(confirmpassword: String) {
        user.confirmpassword = confirmpassword
    }

    func validateUser() -> UserValidationState {
        if (username.isBlank || password.isBlank || confirmpassword.isBlank) {
            return .InValid("Please fill all the fields")
        } else {
            if isNumber(username: username) {
                if isValidPhone(phone: username) {
                    if isValidPasswordLength(password: password) {
                        if passwordsMatch(password: password, confirmpassword: confirmpassword) {
                            return .Valid
                        }
                        return .InValid("Passwords do not match")
                    }
                    return .InValid("Password length doesn't meet criteria")
                }
                return .InValid("InValid Phone")
            } else {
                if isValidEmail(email: username) {
                    if isValidPasswordLength(password: password) {
                        if passwordsMatch(password: password, confirmpassword: confirmpassword) {
                            return .Valid
                        }
                        return .InValid("Passwords do not match")
                    }
                    return .InValid("Password length doesn't meet criteria")
                }
                return .InValid("InValid Email")
           }
        }
    }

    func isValidEmail(email:String) -> Bool {
        let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
        return NSPredicate(format:"SELF MATCHES %@", emailRegEx).evaluate(with: email)
    }

    func isValidPhone(phone: String) -> Bool {
        return true
    }

    func isBlank(text: String) -> Bool {
        return text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }

    func isValidPasswordLength(password: String) -> Bool {
        guard password.count < minPasswordLength else {
            return true
        }
        return false
    }

    func passwordsMatch(password: String, confirmpassword: String) -> Bool {
        guard password == confirmpassword else {
            return false
        }
        return true
    }

    func isNumber(username: String) -> Bool {
        guard let _ = Int(username) else {
            return false
        }
        return true
    }
}

用户.swift

import Foundation

struct User {    
    var username: String?
    var password: String?
    var confirmpassword: String?
}

【问题讨论】:

    标签: ios swift mvvm data-binding


    【解决方案1】:

    数据绑定是 MVVM 的基础。因此,数据绑定可以帮助您将所有业务逻辑排除在视图之外,并与发送和接收数据异步工作。将值传递给 viewModel 似乎没问题,但在某些情况下,您需要将值从 ViewModels 传递给 ViewControllers。例如,您有响应某些数据的异步 API 请求。在 MVVM 中,您会将该数据存储在您的 ViewModel 中,但您的 ViewController 需要被通知收到了一些数据。数据绑定有助于用更少的代码解决这些情况。是的,您可以仅通过使用回调来在没有数据绑定的情况下工作,但这意味着您必须编写大量样板代码。

    我知道 KVO、Rx 和 Reactive 似乎很难。因此,您可以从仅提供绑定功能的简单库开始,而无需深入研究复杂的内容。查看这些库:

    https://github.com/ReactiveKit/Bond

    https://github.com/blendle/Hanson

    请注意,您的编码方式更像是 MVP(模型视图演示器)。如果您不喜欢响应式编程,可以查看该设计架构。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-08
      • 1970-01-01
      • 2014-02-16
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      • 2019-01-31
      相关资源
      最近更新 更多