如何实现带额外校验的UISwitch与ControlProperty<Bool>双向绑定
问题根源
你当前方案的Bug本质是UISwitch.rx.isOn序列会响应所有状态变更事件,包括用户手动操作、代码主动赋值两种场景,因此ControlProperty外部更新同步到开关状态时,也会触发你写的校验逻辑,导致误弹出提示。
解决方案
你可以用UIControl的valueChanged控制事件替代rx.isOn的绑定来监听用户操作,该事件仅会在用户手动交互修改控件状态时触发,代码主动修改isOn属性不会触发该事件,完全符合你的需求。
修改后的完整代码
// 保留原有的单向绑定:ControlProperty 外部变更时无条件同步到 UISwitch property.bind(to: cell.switch.rx.isOn) .disposed(by: cell.disposeBag) // 仅监听用户手动触发的开关变更事件 cell.switch.rx.controlEvent(.valueChanged) .withLatestFrom(cell.switch.rx.isOn) .subscribe(onNext: { [unowned self, weak cell] isOn in if !isOn || viewModel.allowTurnEmailNotificationOn { property.onNext(isOn) } else { let alert = MyAlertViewController() present(alert, animated: true) { // 回滚开关状态,该赋值操作不会触发 valueChanged 事件 cell?.switch.isOn = false } } }) .disposed(by: cell.disposeBag)
逻辑验证
- 用户手动切开关到ON:触发
valueChanged事件,正常走校验逻辑,不符合条件时回滚开关状态、不修改property - 用户手动切开关到OFF:触发
valueChanged事件,直接更新property为false property外部更新:通过单向绑定同步到开关,不会触发valueChanged事件,无多余校验,也不会误弹提示
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

