You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于选中的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:36:25