顺便说一句,来自书"Intro To Rx":
主题提供了一种方便的方式来查看 Rx,但不建议将它们用于日常使用。
你不应该把所有这些主题都混在一起......
首先让我们创建您的业务规则:
// Case 1
func eitherFilled(first: String?, second: String?) -> Bool {
first != nil && !first!.isEmpty || second != nil && !second!.isEmpty
}
// Case 2
func hasError(first: String?, second: String?) -> Bool {
first == nil || second == nil || first != second
}
您可以独立于 Rx 或其他任何东西来测试它们,以确保它们是正确的。
现在创建您的视图模型:
// Case 1
func buttonEnabled(first: Observable<String?>, second: Observable<String?>) -> Observable<Bool> {
Observable.combineLatest(first, second, resultSelector: eitherFilled)
}
// Case 2
func displayError(first: Observable<String?>, second: Observable<String?>) -> Observable<Void> {
Observable.combineLatest(first, second, resultSelector: hasError)
.filter { $0 }
.map { _ in }
}
同样,这些都非常容易使用 RxTest 进行测试。
现在您可以将视图模型安装到视图控制器中,并且您知道它们可以工作,因为您已经对其进行了测试。 (注意:我没有测试过它们。我把它留给你来确保逻辑是正确的。)
final class MyViewController: UIViewController {
@IBOutlet weak var otpField: UITextField!
@IBOutlet weak var confirmOtpField: UITextField!
@IBOutlet weak var button: UIButton!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// Case 1
buttonEnabled(
first: otpField.rx.text.asObservable(),
second: confirmOtpField.rx.text.asObservable()
)
.bind(to: button.rx.isEnabled)
.disposed(by: disposeBag)
// Case 2
displayError(
first: otpField.rx.text.asObservable(),
second: confirmOtpField.rx.text.asObservable()
)
.bind {
finalPresentScene(animated: true) {
UIAlertController(title: "Error", message: "OTP fileds do not match.", preferredStyle: .alert).scene { $0.connectOK() }
}
}
.disposed(by: disposeBag)
}
}
因此,有了以上所有内容,您有两个模型代表您的业务规则,两个视图模型将这些业务规则转换为视图更新,您的视图控制器用于将视图模型连接到视图。
(如果您想了解更多关于我用来呈现警报的代码,请参阅此 GitHub 存储库:https://github.com/danielt1263/CLE-Architecture-Tools)