我可以使用没有数据绑定的MVVM吗?

时间:2017-12-08 12:20:58

标签: ios swift mvvm data-binding

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

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
    }
}

User.swift

import Foundation

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

1 个答案:

答案 0 :(得分:1)

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

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

https://github.com/ReactiveKit/Bond

https://github.com/blendle/Hanson

仅仅是为了注意,你编码的方式更像是MVP(模型视图演示者)。如果你不喜欢被动编程,你可以检查一下这个设计架构。