RxSwift中TableView+UIAlertAction数据流异常:首次无值、重复发送求助
问题分析与解决方案
我来帮你捋清楚问题所在,以及怎么修复这些异常:
为什么会出现这些问题?
- 点Cell就发送数据:你在
modelSelected的订阅里直接触发了后续逻辑,但这个订阅会在你点击Cell的瞬间就执行,根本不等你点击Ok按钮。 - 首次点击Ok无数据:在Ok按钮的回调里,你又重新订阅了
modelSelected,但这个新订阅是在点击Cell之后才创建的,已经错过了之前点击Cell产生的事件,自然收不到数据。 - 数据量递增:每次弹窗你都会新增一个
modelSelected的订阅,这些订阅都存在disposeBag里不会自动销毁,导致后续点击时多个订阅同时触发,数据量越来越多。
修正后的代码实现
ViewController 部分
func bindTableView() { viewModel.stationItems.bind(to: addTableView.rx.items(cellIdentifier: "addCell", cellType: AddTableViewCell.self)) { (row, item, cell) in cell.cellAdd = item }.disposed(by: disposeBag) addTableView.rx.modelSelected(StationItem.self) .subscribe(onNext: { [weak self] selectedItem in guard let self = self else { return } let alert = UIAlertController(title: "Add Station", message: "Do you want to add a station to your favorites?", preferredStyle: .alert) // Ok按钮直接使用之前选中的item let okAction = UIAlertAction(title: "Ok", style: .default) { [weak self] _ in guard let self = self else { return } self.viewModel.addStationItem(with: selectedItem) } alert.addAction(okAction) // 取消按钮用.cancel风格更符合iOS规范 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) alert.addAction(cancelAction) DispatchQueue.main.async { self.present(alert, animated: true) } }).disposed(by: disposeBag) viewModel.fetchStations() }
ViewModel 部分
根据你的需求,有两种实现方式:
方式1:直接通过方法参数传递数据(推荐,更简洁)
// 去掉原来的stationItem Subject,直接用方法接收参数 func addStationItem(with item: StationItem) { print("Data: \(item)") print("ADD:") // 在这里执行添加收藏的逻辑,比如存入本地数据库或请求接口 }
方式2:保留Subject(如果需要在其他地方也传递StationItem数据)
let stationItem = PublishSubject<StationItem>() init() { // 只订阅一次,不要在addStationItem里重复订阅 stationItem.subscribe(onNext: { data in print("Data: \(data)") }).disposed(by: disposeBag) } func addStationItem(with item: StationItem) { // 发送事件到Subject stationItem.onNext(item) print("ADD:") }
关键修改点说明
- 保存选中的Item:点击Cell时就把
selectedItem存下来,Ok按钮回调直接使用这个对象,避免重复订阅modelSelected。 - 避免重复订阅:ViewModel的Subject订阅只在初始化时做一次,不会每次调用
addStationItem都新增订阅,解决数据递增问题。 - 弱引用self:使用
[weak self]避免循环引用,防止内存泄漏。 - 规范AlertAction风格:取消按钮用
.cancel风格,符合iOS的交互设计规范。
这样修改后,就能实现首次点击Ok按钮就传递Cell数据,且仅发送单次数据的需求了。
内容的提问来源于stack exchange,提问作者beginner992
相关产品推荐
相关产品推荐

