觀察者
和 被觀察者(Observable)發出序列
ControlProperty<String>
,最終遵循 ObservableType
協議ControlEvent<Void>
,最終遵循 ObservableType
協議UIBindingObserver<UIElementType, Value>
(遵循 ObserverType
協議) 來生成觀察者,對接受的數據條件進行判斷是否能夠輸入、可點擊// MARK: RX 擴展 計算型屬性 // textfield 根據展現驗證後的結果可否輸入,驗證過了才能輸入 extension Reactive where Base: UITextField { var inputEnable: UIBindingObserver<Base, ValidationResult> { return UIBindingObserver(UIElement: base, binding: { (textField, result) in textField.isEnabled = result.isValid }) } }
Subject
被觀察者(Observable)
的一些經常使用的 api
以前 MVC 的與 iOS 裏的 Controller、View 一一對應,很好理解,而 MVVM 裏 Controller 屬於 V 了,負責處理控制器跳轉和將 View 和 VM 綁定等,大部分的業務邏輯代碼都在 VM 裏,感受應該是這樣
git
自始至終感受 iOS 裏的 model 這一層很輕,有時僅僅是創建了模型類而已。感受應該是各類數據操做如數據庫查詢等都應該是 model 這一層的github
** 雙向綁定 **
override func viewDidLoad() { super.viewDidLoad() let regiestViewModel = RegiestViewModel() // 這裏作綁定: UI控件 --> VM VM -> UI控件 // 1.UI控件 --> VM nameTextField.rx.text.orEmpty .bindTo(regiestViewModel.username) .addDisposableTo(disposeBag) pwdTextField.rx.text.orEmpty .bindTo(regiestViewModel.userPwd) .addDisposableTo(disposeBag) repeatPwdTextField.rx.text.orEmpty .bindTo(regiestViewModel.repeatPwd) .addDisposableTo(disposeBag) regiestBtn.rx.tap .bindTo(regiestViewModel.registerTaps) .addDisposableTo(disposeBag) // 2.VM -> UI控件 // 顯示結果的 label 上 regiestViewModel.usernameValid .bindTo(nameTipLabel.rx.validResult) .addDisposableTo(disposeBag) // 綁定 密碼框是否能夠輸入 regiestViewModel.usernameValid .bindTo(pwdTextField.rx.inputEnable) .addDisposableTo(disposeBag) regiestViewModel.passwordValid .bindTo(pwdTipLabel.rx.validResult) .addDisposableTo(disposeBag) regiestViewModel.passwordValid .bindTo(repeatPwdTextField.rx.inputEnable) .addDisposableTo(disposeBag) regiestViewModel.repeatPwdValid .bindTo(repeatPwdTipLabel.rx.validResult) .addDisposableTo(disposeBag) // 按鈕不是綁定, 按鈕是 subcribe, 須要操做的 regiestViewModel.registerButtonEnabled .subscribe (onNext: { [weak self] (result) in self?.regiestBtn.isEnabled = result self?.regiestBtn.alpha = result ? 1 : 0.8 }) .addDisposableTo(disposeBag) // 註冊結果 : 註冊成果或失敗 要展現在 UI 上 regiestViewModel.registeResult .subscribe(onNext:{ [weak self] result in switch result { case let .failed(message): self?.showAlter(message: message) case let .ok(message): self?.showAlter(message: message) case .empty: self?.showAlter(message: "") } }) .addDisposableTo(disposeBag) // 跳轉到登陸界面按鈕的點擊 loginVcBtn.rx.tap .subscribe(onNext: { let loginVc = LoginViewController() loginVc.title = "請登陸" self.navigationController?.pushViewController(loginVc, animated: true) }) .addDisposableTo(disposeBag) }
tableView
swift let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, HerosItem>>()
控制器裏用這個 dataSource 配置 cell數據庫
dataSource.configureCell = { (_, tableView, indexPath, item) in var cell = tableView.dequeueReusableCell(withIdentifier: "herosCell") if cell == nil { cell = UITableViewCell(style: .subtitle, reuseIdentifier: "herosCell") } cell!.imageView?.image = UIImage(named: item.icon) cell!.textLabel?.text = item.name cell!.detailTextLabel?.text = item.intro return cell! }
用 VM 建立出數據 Observable,發出序列,綁定到dataSource 上,完成數據的綁定編程
homeViewMode.getSearchResult() .bindTo(tableView.rx.items(dataSource: dataSource)) .addDisposableTo(disposeBag)
swift tableView.rx .setDelegate(self) .addDisposableTo(disposeBag)
tableView.rx.itemSelected .map { [weak self] indexPath in return (indexPath, self?.dataSource[indexPath]) } .subscribe(onNext: {(indexPath, item) in self.showAlter(item: item) }) .addDisposableTo(disposeBag)
另外若是作實時搜索的話,用雙向綁定效果那是極好的,將搜索框的搜索關鍵字綁定到 VM 裏,在用 VM 產生序列綁定到 tableView 上swift