如何基于选中的UIButton创建RxSwift序列及相关技术疑问
RxSwift 多控件选中联动与模型处理方案
1. 基于UIControl的isSelected属性创建点击序列
通过监听按钮的rx.tap事件,每次点击切换isSelected状态,并将状态变化转化为可观察序列,同时用startWith初始化初始状态:
// 第一个按钮的选中状态序列 let firstButtonSelection = firstButton.rx.tap .map { [weak firstButton] in firstButton?.isSelected.toggle() return firstButton?.isSelected ?? false } .startWith(firstButton.isSelected) // 第二个按钮的选中状态序列 let secondButtonSelection = secondButton.rx.tap .map { [weak secondButton] in secondButton?.isSelected.toggle() return secondButton?.isSelected ?? false } .startWith(secondButton.isSelected) // 第三个按钮的选中状态序列 let thirdButtonSelection = thirdButton.rx.tap .map { [weak thirdButton] in thirdButton?.isSelected.toggle() return thirdButton?.isSelected ?? false } .startWith(thirdButton.isSelected)
2. 不可变Model的可观察模型更新方案
由于Model是不可变值类型,每次状态变化需要创建新实例。使用BehaviorRelay持有当前模型状态(替代原有的只读Observable<Model>),合并三个按钮的状态序列生成新模型并更新Relay:
步骤1:替换为BehaviorRelay存储模型
// 初始化初始模型(可结合本地存储读取,见问题3) let initialModel = Model(isFirstButtonSelected: false, isSecondButtonSelected: false, isThirdButtonSelected: false) let modelRelay = BehaviorRelay(value: initialModel) let model: Observable<Model> = modelRelay.asObservable()
步骤2:合并状态序列更新模型
Observable.combineLatest(firstButtonSelection, secondButtonSelection, thirdButtonSelection) .subscribe(onNext: { firstSelected, secondSelected, thirdSelected in // 创建新的Model实例 let newModel = Model( isFirstButtonSelected: firstSelected, isSecondButtonSelected: secondSelected, isThirdButtonSelected: thirdSelected ) // 更新Relay,发送新模型 modelRelay.accept(newModel) }) .disposed(by: disposeBag)
步骤3:订阅模型变化更新UI
model.subscribe(onNext: { [weak self] model in self?.configure(model) }) .disposed(by: disposeBag)
3. 选中值的存储与恢复
以UserDefaults为例,让Model遵守Codable协议实现序列化存储:
步骤1:让Model遵守Codable
struct Model: Codable { let isFirstButtonSelected: Bool let isSecondButtonSelected: Bool let isThirdButtonSelected: Bool }
步骤2:模型变化时保存到UserDefaults
modelRelay.subscribe(onNext: { model in do { let data = try JSONEncoder().encode(model) UserDefaults.standard.set(data, forKey: "SelectedButtonsModel") } catch { print("保存选中状态失败:\(error)") } }) .disposed(by: disposeBag)
步骤3:初始化时读取保存的状态
var initialModel = Model(isFirstButtonSelected: false, isSecondButtonSelected: false, isThirdButtonSelected: false) // 读取本地存储的状态 if let savedData = UserDefaults.standard.data(forKey: "SelectedButtonsModel") { do { initialModel = try JSONDecoder().decode(Model.self, from: savedData) } catch { print("读取选中状态失败:\(error)") } } let modelRelay = BehaviorRelay(value: initialModel) let model: Observable<Model> = modelRelay.asObservable()
额外:Next按钮启用状态联动
合并三个选中序列,判断是否至少有一个按钮选中,绑定到Next按钮的isEnabled:
Observable.combineLatest(firstButtonSelection, secondButtonSelection, thirdButtonSelection) .map { $0 || $1 || $2 } .bind(to: nextButton.rx.isEnabled) .disposed(by: disposeBag)
内容的提问来源于stack exchange,提问作者nsus
相关产品推荐
相关产品推荐

