你好 RxSwift!

    • 当用户输入用户名时,如果用户名不足 5 个字就给出红色提示语,并且无法输入密码,当用户名符合要求时才可以输入密码。
    • 同样的当用户输入的密码不到 5 个字时也给出红色提示语。
    • 当用户名和密码有一个不符合要求时底部的绿色按钮不可点击,只有当用户名和密码同时有效时按钮才可点击。
    • 当点击绿色按钮后弹出一个提示框,这个提示框只是用来做演示而已。

    你可以下载这个例子并在模拟器上运行,这样可以帮助于你理解整个程序的交互:

    1. 用户名输入框
    2. 用户名提示语(红色)
    3. 密码输入框
    4. 密码提示语(红色)
    5. 操作按钮(绿色)
    • 当用户名输入不到 5 个字时显示提示语,并且无法输入密码

      2. 你好 RxSwift! - 图2

      1. super.viewDidLoad()
      2. ...
      3. // 用户名是否有效
      4. let usernameValid = usernameOutlet.rx.text.orEmpty
      5. // 用户名 -> 用户名是否有效
      6. .map { $0.count >= minimalUsernameLength }
      7. .share(replay: 1)
      8. ...
      9. // 用户名是否有效 -> 密码输入框是否可用
      10. usernameValid
      11. .bind(to: passwordOutlet.rx.isEnabled)
      12. .disposed(by: disposeBag)
      13. // 用户名是否有效 -> 用户名提示语是否隐藏
      14. usernameValid
      15. .bind(to: usernameValidOutlet.rx.isHidden)
      16. .disposed(by: disposeBag)
      17. ...
      18. }

      当用户修改用户名输入框的内容时就会产生一个新的用户名, 然后通过 map 方法将它转化成用户名是否有效, 最后通过 bind(to: ...) 来决定密码输入框是否可用以及提示语是否隐藏。

    • 当密码输入不到 5 个字时显示提示文字

      这个和用用户名来控制提示语的逻辑是一样的。

    • 点击绿色按钮后,弹出一个提示框

    这样 4 个交互都完成了,现在我们纵观全局看下这个程序是一个什么样的结构:

    2. 你好 RxSwift! - 图6

    然后看一下完整的代码:

    1. override func viewDidLoad() {
    2. super.viewDidLoad()
    3. usernameValidOutlet.text = "Username has to be at least \(minimalUsernameLength) characters"
    4. passwordValidOutlet.text = "Password has to be at least \(minimalPasswordLength) characters"
    5. let usernameValid = usernameOutlet.rx.text.orEmpty
    6. .map { $0.count >= minimalUsernameLength }
    7. .share(replay: 1)
    8. .map { $0.count >= minimalPasswordLength }
    9. .share(replay: 1)
    10. let everythingValid = Observable.combineLatest(
    11. usernameValid,
    12. passwordValid
    13. ) { $0 && $1 }
    14. usernameValid
    15. .bind(to: passwordOutlet.rx.isEnabled)
    16. .disposed(by: disposeBag)
    17. usernameValid
    18. .bind(to: usernameValidOutlet.rx.isHidden)
    19. .disposed(by: disposeBag)
    20. passwordValid
    21. .bind(to: passwordValidOutlet.rx.isHidden)
    22. .disposed(by: disposeBag)
    23. everythingValid
    24. .bind(to: doSomethingOutlet.rx.isEnabled)
    25. .disposed(by: disposeBag)
    26. doSomethingOutlet.rx.tap
    27. .subscribe(onNext: { [weak self] in self?.showAlert() })
    28. .disposed(by: disposeBag)
    29. }
    30. func showAlert() {
    31. let alertView = UIAlertView(
    32. title: "RxExample",
    33. message: "This is wonderful",
    34. delegate: nil,
    35. cancelButtonTitle: "OK"
    36. )
    37. alertView.show()
    38. }

    你会发现你可以用几行代码完成如此复杂的交互。这可以大大提升我们的开发效率。

    • 和我们所熟悉的对象一样,每一个绑定也是有生命周期的。并且这个绑定是可以被清除的。disposed(by: disposeBag)就是将绑定的生命周期交给 disposeBag 来管理。当 disposeBag 被释放的时候,那么里面尚未清除的绑定也就被清除了。这就相当于是在用 来管理绑定的生命周期。 这个内容会在 Disposable 章节详细介绍。