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

RxSwift问题:搜索结果的条目数与收藏数无法在视图更新

解决RxSwift TodoList搜索时计数视图不更新的问题

我帮你定位到问题核心了!你当前的实现中,itemCountObservable和favCountObservable是一次性的Observable(用.just创建),当你在搜索回调里重新给这两个变量赋值新的.just Observable时,视图已经和初始的Observable完成绑定了,新的Observable根本没机会和视图建立绑定关系,所以数值更新了但视图没反应。

正确的做法是用BehaviorRelay来持有计数状态,它可以动态发送新值,并且订阅者能持续接收更新。下面是具体的修改方案:

步骤1:修改MainTabViewModel的状态持有方式

把原来的itemCountObservable和favCountObservable改成用BehaviorRelay存储状态,再通过asObservable()暴露给视图绑定:

final class MainTabViewModel {
    private let disposeBag = DisposeBag()
    private let userDefault: UserDefaultManager
    var dispItems = BehaviorRelay<[SectionModel]>(value: [])
    private let shared = Sharing.shared
    
    // 用BehaviorRelay持有计数状态
    private let itemCountRelay = BehaviorRelay<String>(value: "")
    private let favCountRelay = BehaviorRelay<String>(value: "")
    
    // 对外暴露Observable供视图绑定
    var itemCountObservable: Observable<String> { itemCountRelay.asObservable() }
    var favCountObservable: Observable<String> { favCountRelay.asObservable() }
    
    init(searchTextObservable: Observable<String>, userDefault: UserDefaultManager = UserDefault()) {
        self.userDefault = userDefault
        let initialValue = shared.list
        shared.listItems.accept(initialValue)
        dispItems = shared.listItems
        
        // 设置初始计数
        updateCounts(with: shared.list[0].list)
        
        searchTextObservable.subscribe(onNext: { text in
            if text.isEmpty {
                let initialValue = self.shared.list
                self.shared.listItems.accept(initialValue)
                self.dispItems = self.shared.listItems
                // 更新初始状态的计数
                self.updateCounts(with: self.shared.list[0].list)
            }else{
                let filteredItems: [Item] = self.shared.list[0].list.filter { $0.name.contains(text) }
                let filteredList = [SectionModel(list: filteredItems)]
                self.shared.listItems.accept(filteredList)
                self.dispItems = self.shared.listItems
                // 更新筛选后的计数
                self.updateCounts(with: filteredItems)
                print("\(filteredItems.count) items")
            }
        }).disposed(by: disposeBag)
    }
    
    // 提取更新计数的复用方法
    private func updateCounts(with items: [Item]) {
        let itemCount = items.count
        itemCountRelay.accept("\(itemCount) items")
        
        let favCount = shared.calcFavCount(array: items)
        favCountRelay.accept("\(favCount)")
    }
}

步骤2:优化Sharing类的calcFavCount方法(可选但推荐)

你的计数方法可以简化成更Swifty的写法:

extension Sharing {
    func calcFavCount(array: [Item]) -> Int {
        array.filter(\.fav).count
    }
}

为什么这样修改有效?

  • BehaviorRelay是RxSwift里用来持有可变状态的容器,它可以随时调用accept(_:)发送新值,所有订阅它的Observable的观察者都会收到更新。
  • 视图在listDetailSetup()里绑定的是itemCountObservable(也就是Relay的asObservable()),只要Relay发送新值,视图就会自动更新。
  • 提取updateCounts方法让代码更简洁,避免重复逻辑。

这样修改后,当你在搜索栏输入文本时,筛选后的条目数和收藏数就会实时同步到对应的Label上了!

内容的提问来源于stack exchange,提问作者lyn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:55:48