RxSwift:UITabBarController中UICollectionView添加收藏后不更新问题
解决UITabBarController中收藏列表UICollectionView不更新的问题
这个问题的核心在于你的FavouriteViewModel没有监听Realm数据库的实时变化,仅在手动调用fetchDateFromDb时才会推送数据。当第一个VC修改数据库后,第二个VC的ViewModel没有感知到这个变化,所以UICollectionView不会更新。下面是具体的解决方案:
1. 改用Realm的实时通知机制监听数据变化
Realm本身提供了对查询结果的实时监听能力,我们可以利用这个特性在数据库数据变化时自动推送新的列表数据。同时把PublishSubject换成BehaviorSubject(或者RxCocoa的PublishRelay),这样新订阅的观察者能立即拿到当前最新的数据,而不是只有订阅后的新事件。
修改FavouriteViewModel代码
import RealmSwift import RxSwift import RxCocoa class FavouriteViewModel { // 用BehaviorSubject保存当前文章列表,初始值为空数组 let articlesSubject: BehaviorSubject<[ArticleModel]> = BehaviorSubject(value: []) // Realm通知的Token,用于在销毁时移除监听 private var notificationToken: NotificationToken? private let disposeBag = DisposeBag() init() { // 初始化时就启动Realm监听 setupRealmNotification() // 先获取一次初始数据 fetchDateFromDb() } deinit { // 移除Realm通知监听,避免内存泄漏 notificationToken?.invalidate() } func fetchDateFromDb(){ let articleList = DatabaseManager.shared.getAllArticle().toArray() articlesSubject.onNext(articleList) } private func setupRealmNotification() { // 获取Realm的查询结果(注意Realm的Results是实时的) let results = DatabaseManager.shared.getAllArticle() // 监听查询结果的变化 notificationToken = results.observe { [weak self] change in guard let self = self else { return } switch change { case .initial(let results): // 初始加载数据(可选,因为fetchDateFromDb已经调用过) self.articlesSubject.onNext(results.toArray()) case .update(let results, _, _, _): // 数据发生更新,推送新的列表 self.articlesSubject.onNext(results.toArray()) case .error(let error): // 处理监听错误 print("Realm通知错误: \(error.localizedDescription)") } } } }
2. 确保FavouriteVC的绑定逻辑兼容BehaviorSubject
你的setupBinds代码不需要做太多修改,因为BehaviorSubject会在订阅时自动发送当前的最新值,确保UICollectionView能加载初始数据:
private func setupBinds(){ self.favArticleCollectionView.register(UINib(nibName: "PreviewItemVCell", bundle: nil), forCellWithReuseIdentifier: PreviewItemVCell.identifier) viewModel .articlesSubject .observeOn(MainScheduler.instance) .bind(to: self.favArticleCollectionView.rx.items(cellIdentifier: PreviewItemVCell.identifier, cellType: PreviewItemVCell.self)) { (item, article,cell) in cell.article = article }.disposed(by: disposeBag) }
3. 可选补充:在viewWillAppear时手动刷新
为了确保用户切回收藏页面时数据绝对最新,可以在FavouriteVC的viewWillAppear中手动调用一次数据刷新:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) viewModel.fetchDateFromDb() }
为什么原来的代码无法更新?
- 你使用的
PublishSubject是“冷”的,只有在调用onNext时才会发送数据,而数据库变化时没有触发这个操作。 FavouriteViewModel没有监听Realm的实时变化,无法感知第一个VC对数据库的修改,自然不会主动推送新数据给UICollectionView。
内容的提问来源于stack exchange,提问作者Vadym Marchenko
相关产品推荐
相关产品推荐

