RxSwift中等待多API完成后刷新UITableView问题求助
解决RxSwift双API请求后仅刷新一次UITableView的问题
你遇到的「Done打印两次」问题,核心原因大概率是Observable被重复订阅,或是其中某个API请求的Observable本身多次发射事件。以下是针对性的解决方案:
一、先确保API请求是单次发射事件
首先确认你的API请求Observable是单次触发的(即完成后仅发送一个next事件,随后completed)。封装API请求的方法应类似这样:
func fetchFirstData() -> Observable<[FirstModel]> { return URLSession.shared.rx.data(request: firstApiRequest) .map { data in try JSONDecoder().decode([FirstModel].self, from: data) } .asObservable() } func fetchSecondData() -> Observable<[SecondModel]> { return URLSession.shared.rx.data(request: secondApiRequest) .map { data in try JSONDecoder().decode([SecondModel].self, from: data) } .asObservable() }
二、用Observable.zip实现单次触发(正确写法)
zip的特性是严格等待每个Observable各发射一次事件后,才合并触发一次,完全匹配你的需求。如果之前用zip仍触发多次,检查是否重复订阅了该序列。正确示例:
// 合并两个API请求 Observable.zip(fetchFirstData(), fetchSecondData()) .subscribe(onNext: { firstData, secondData in // 合并数据到数据源 self.dataSource = firstData + secondData // 仅刷新一次TableView self.tableView.reloadData() print("Done") }, onError: { error in print("请求失败:\(error.localizedDescription)") }) .disposed(by: disposeBag) // 必须添加到disposeBag避免内存泄漏
三、排查重复订阅的常见场景
如果仍出现两次打印,检查以下几点:
- 是否在多个生命周期方法(比如
viewDidLoad和viewWillAppear)中重复订阅了同一个合并序列? - 是否每次调用API方法都会创建新请求,且你无意中调用了两次?
- 如果Observable是热序列,添加
.share(replay: 1, scope: .whileConnected)确保共享订阅,避免重复触发。
四、语义化替代方案:Single.zip
API请求通常是「单次成功/失败」,用Single更贴合场景,Single.zip只会在两个请求都成功后触发一次:
// 将API请求改为Single类型 func fetchFirstData() -> Single<[FirstModel]> { return URLSession.shared.rx.data(request: firstApiRequest) .map { try JSONDecoder().decode([FirstModel].self, from: $0) } .asSingle() } func fetchSecondData() -> Single<[SecondModel]> { return URLSession.shared.rx.data(request: secondApiRequest) .map { try JSONDecoder().decode([SecondModel].self, from: $0) } .asSingle() } // 合并订阅 Single.zip(fetchFirstData(), fetchSecondData()) .subscribe(onSuccess: { firstData, secondData in self.dataSource = firstData + secondData self.tableView.reloadData() print("Done") }, onFailure: { error in print("请求失败:\(error)") }) .disposed(by: disposeBag)
内容的提问来源于stack exchange,提问作者cMoNz
相关产品推荐
相关产品推荐

