Observables 绑定 2 个文本字段
Observables bind 2 textfields
所以现在在我正在开发的应用程序中,我决定通过转向 MVVM 设计模式来重构它。在这里,我认识了著名的“Observables”。
在使用 MVVM 时,我设法理解了它们是如何工作的以及它们存在的重要性,我已经阅读了一些关于不同实现技术的解释。我的意思是技术:
- Observables (我目前正在使用的那个)
- 事件总线/通知中心
- FRP 技术(ReactiveCocoa / RxSwift)
我已经这样声明了我的 Bindable class:
import UIKit
class Bindable<T> {
var value: T? {
didSet {
observer?(value)
}
}
var observer: ((T?) -> ())?
func bind(observer: @escaping (T?) -> ()) {
self.observer = observer
}
}
我想做的是绑定 2 个 UITextField 的 (在我的 ViewController's) 与各自的ViewModel。在我的 ViewController 中有 2 个文本字段(emailInput - passwordInput)和一个 'Log In' 按钮,我希望它被禁用,除非两个文本字段都不为空。
为此,我添加了两个文本字段的这个目标:
emailInput.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
passwordInput.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
然后:
/// Enable / Disable --> Log In button
@objc func textFieldDidChange(_ textField: UITextField) {
if (emailInput.text == "") || (passwordInput.text == "") {
logInButton.enableButton(false)
} else {
logInButton.enableButton(true)
}
}
但我的问题是......我如何在我的 ViewModel 中实现同样的东西??
是否可以使用我的 Bindable class 进行双向绑定?
(如果需要更多代码来解决这个问题,请告诉我,我会编辑问题)
Observable 用于将更改从视图模型传递到视图。您的视图模型无需使用 Observable 模式来响应文本字段中的更新。你可以提供一个简单的函数setCredentials(email: String, password: String)
。在此函数中,您可以检查这些值是否为空并设置 var loginEnabled: Bindable<Bool>
。您的视图观察 loginEnabled
并相应地设置登录按钮状态。
struct ViewModel {
var loginEnabled = Bindable<Bool>()
var email = ""
var password = ""
init() {
self.loginEnabled.value = false
}
func setCredentials(email: String, password: String) {
self.email = email
self.password = password
self.loginEnabled.value = !email.isEmpty && !password.isEmpty
}
}
然后在你的视图控制器中你有类似
的东西
var viewModel: ViewModel
override func viewDidLoad {
super.viewDidLoad()
self.viewModel.loginEnabled.bind { value in
self.logInButton.isEnabled = value ?? false
}
}
@objc func textFieldDidChange(_ textField: UITextField) {
self.viewModel.setCredentials(email: self.emailInput.text ?? "", password: self.passwordInput.text ?? "")
}
所以现在在我正在开发的应用程序中,我决定通过转向 MVVM 设计模式来重构它。在这里,我认识了著名的“Observables”。
在使用 MVVM 时,我设法理解了它们是如何工作的以及它们存在的重要性,我已经阅读了一些关于不同实现技术的解释。我的意思是技术:
- Observables (我目前正在使用的那个)
- 事件总线/通知中心
- FRP 技术(ReactiveCocoa / RxSwift)
我已经这样声明了我的 Bindable class:
import UIKit
class Bindable<T> {
var value: T? {
didSet {
observer?(value)
}
}
var observer: ((T?) -> ())?
func bind(observer: @escaping (T?) -> ()) {
self.observer = observer
}
}
我想做的是绑定 2 个 UITextField 的 (在我的 ViewController's) 与各自的ViewModel。在我的 ViewController 中有 2 个文本字段(emailInput - passwordInput)和一个 'Log In' 按钮,我希望它被禁用,除非两个文本字段都不为空。
为此,我添加了两个文本字段的这个目标:
emailInput.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
passwordInput.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
然后:
/// Enable / Disable --> Log In button
@objc func textFieldDidChange(_ textField: UITextField) {
if (emailInput.text == "") || (passwordInput.text == "") {
logInButton.enableButton(false)
} else {
logInButton.enableButton(true)
}
}
但我的问题是......我如何在我的 ViewModel 中实现同样的东西??
是否可以使用我的 Bindable class 进行双向绑定?
(如果需要更多代码来解决这个问题,请告诉我,我会编辑问题)
Observable 用于将更改从视图模型传递到视图。您的视图模型无需使用 Observable 模式来响应文本字段中的更新。你可以提供一个简单的函数setCredentials(email: String, password: String)
。在此函数中,您可以检查这些值是否为空并设置 var loginEnabled: Bindable<Bool>
。您的视图观察 loginEnabled
并相应地设置登录按钮状态。
struct ViewModel {
var loginEnabled = Bindable<Bool>()
var email = ""
var password = ""
init() {
self.loginEnabled.value = false
}
func setCredentials(email: String, password: String) {
self.email = email
self.password = password
self.loginEnabled.value = !email.isEmpty && !password.isEmpty
}
}
然后在你的视图控制器中你有类似
的东西
var viewModel: ViewModel
override func viewDidLoad {
super.viewDidLoad()
self.viewModel.loginEnabled.bind { value in
self.logInButton.isEnabled = value ?? false
}
}
@objc func textFieldDidChange(_ textField: UITextField) {
self.viewModel.setCredentials(email: self.emailInput.text ?? "", password: self.passwordInput.text ?? "")
}