这个问题可能看起来很基本,但我发帖是为了得到建议。
以下是使用MVVM模式的示例登录模块。
viewcontroller代码如下。
class ViewController: UIViewController {
private var loginviewmodel = LoginViewModel()
@IBOutlet weak var textFieldUserName: UITextField!
@IBOutlet weak var textFieldPassword: UITextField!
@IBAction func signIn(_ sender: Any) {
//CASE 1
loginviewmodel.performLogin(name: textFieldUserName.text!, pwd: textFieldPassword.text!)
//CASE 2
//loginviewmodel.performLogin()
}
override func viewDidLoad() {
super.viewDidLoad()
textFieldUserName.delegate = self
textFieldPassword.delegate = self
}
}
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let inputText = (textField.text! as NSString).replacingCharacters(in: range, with: string)
switch textField {
case textFieldUserName:
loginviewmodel.updateUsername(inputText: inputText)
case textFieldPassword:
loginviewmodel.updatePassword(inputText: inputText)
default:
return false
}
return true
}
}
视图模型代码如下。
class LoginViewModel {
var userName: String?
var password: String?
func updateUsername(inputText: String) {
self.userName = inputText
}
func updatePassword(inputText: String) {
self.password = inputText
}
func performLogin() {
print("Login successful with username = \(userName) and password = \(password).")
}
func performLogin(name: String, pwd: String) {
print("Login successful with username = \(name) and password = \(pwd).")
}
}
我有两种情况,其中值以不同方式从viewcontroller传递到viewmodel。
第一种将文本作为函数参数直接传递的情况
第二种情况,通过文本委托方法
这会是首选方式吗?
答案 0 :(得分:1)
我更喜欢第二种情况
loginviewmodel.performLogin()
通过使用委托,您还可以在用户输入时验证两个文本字段中的输入,而不是等待用户输入错误数据然后验证
答案 1 :(得分:1)
首选是使用delegate method
程序员工作的一个常见部分是保持UI状态与Model状态同步。和用户输入。当用户与屏幕交互时。这种互动应该立即反映if it useful for user
不要等到他再迈出一步press submit Button
让我们解释一下 假设您的屏幕有2个输入,用户名或电子邮件和密码为TextFields
和一个登录按钮
您需要在允许提交之前对用户输入数据进行一些验证。例如,需要验证密码和电子邮件验证的字符数等...
没有代表的第一种方法
没有验证只会在我按下登录后通知用户错误信息,LoginView Model在用户输入时没有关于ViewController的信息,viewModel只知道用户按下登录按钮时的信息
使用代表的第二种方法
在这种方法中,LoginViewModel现在知道在按下登录按钮之前用户输入的是什么,我们可以执行一些验证来启用或禁用loginButton
<强>的ViewController:强>
class ViewController: UIViewController,LoginViewModelViewDelegate {
private var loginviewmodel = LoginViewModel()
@IBOutlet weak var textFieldUserName: UITextField!
@IBOutlet weak var textFieldPassword: UITextField!
@IBAction func signIn(_ sender: Any) {
loginviewmodel.performLogin()
}
override func viewDidLoad() {
super.viewDidLoad()
// delegate to allow ViewModel notify his view
loginviewmodel.viewDelegate = self
self.textFieldUserName.addTarget(self, action: #selector(userNameFieldDidChange(_:)), for: UIControlEvents.editingChanged)
self.textFieldPassword.addTarget(self, action: #selector(passwordFieldDidChange(_:)), for: UIControlEvents.editingChanged)
}
// MARK: - user Input notification
@objc func userNameFieldDidChange(_ textField: UITextField)
{
if let text = textField.text {
loginviewmodel.userName = text
}
}
@objc func passwordFieldDidChange(_ textField: UITextField)
{
if let text = textField.text {
loginviewmodel.password = text
}
}
// MARK: - LoginViewModel Delegate
func canSubmitStatusDidChange(_ viewModel: LoginViewModel, status: Bool) {
// Enable or disable login button to allow user to submit input
}
}
<强>视图模型:强>
import Foundation
protocol LoginViewModelViewDelegate: class
{
func canSubmitStatusDidChange(_ viewModel: LoginViewModel, status: Bool)
}
class LoginViewModel {
weak var viewDelegate: LoginViewModelViewDelegate?
fileprivate var passwordIsValidFormat: Bool = false
fileprivate var userNameIsValidFormat: Bool = false
/// Submit
var canSubmit: Bool {
return userNameIsValidFormat && passwordIsValidFormat
}
/// Email
var userName: String = "" {
didSet {
if oldValue != userName {
let oldCanSubmit = canSubmit
userNameIsValidFormat = validateUserNameAsEmailFormat(userName)
if canSubmit != oldCanSubmit {
viewDelegate?.canSubmitStatusDidChange(self, status: canSubmit)
}
}
}
}
/// Password
var password: String = "" {
didSet {
if oldValue != password {
let oldCanSubmit = canSubmit
passwordIsValidFormat = validatePasswordFormat(password)
if canSubmit != oldCanSubmit {
viewDelegate?.canSubmitStatusDidChange(self, status: canSubmit)
}
}
}
}
func performLogin() {
// perform Login and you can add anather delegate to notify View with error Message of login thow error
}
fileprivate func validateUserNameAsEmailFormat(_ userName: String) -> Bool
{
let REGEX: String
REGEX = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,32}"
return NSPredicate(format: "SELF MATCHES %@", REGEX).evaluate(with: userName)
}
/// Validate password is at least 6 characters
fileprivate func validatePasswordFormat(_ password: String) -> Bool
{
let trimmedString = password.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
return trimmedString.count > 8
}
}
答案 2 :(得分:0)
请使用此:
class ViewController: UIViewController {
private var loginviewmodel = LoginViewModel()
@IBOutlet weak var textFieldUserName: UITextField!
@IBOutlet weak var textFieldPassword: UITextField!
@IBAction func signIn(_ sender: Any) {
//CASE 1
// Check validation textfield is empty or not
loginviewmodel.performLogin(name: textFieldUserName.text!, pwd: textFieldPassword.text!)
}
override func viewDidLoad() {
super.viewDidLoad()
textFieldUserName.delegate = self
textFieldPassword.delegate = self
}
}
class LoginViewModel {
var userName: String?
var password: String?
func performLogin(name: String, pwd: String) {
print("Login successful with username = \(name) and password = \(pwd).")
}
}