如何在FirebaseUI-IOS中处理UITableView与UICollectionView空数据状态?
处理FirebaseUI iOS中空列表的空视图展示
嘿,我之前在做FirebaseUI iOS的列表展示时也碰到过这个问题!确实官方文档没明确提类似Android OnDataChanged()的回调,但我们可以通过几种灵活的方式来实现空列表状态的处理,下面是我亲测好用的方案:
方法1:直接监听Firestore查询的快照变化
FirebaseUI的数据源本质是基于Firestore查询的,所以我们可以自己监听这个查询的快照更新,根据返回的文档数量来控制空视图的显示:
// 假设你已经初始化了collectionView和dataSource let targetCollection = Firestore.firestore().collection("your_target_collection") // 配置FirebaseUI数据源 dataSource = FUICollectionViewDataSource(query: targetCollection, collectionView: collectionView) { [weak self] collectionView, indexPath, document in guard let self = self else { return UICollectionViewCell() } let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellID", for: indexPath) as! YourCustomCell cell.configure(with: document.data()) return cell } collectionView.dataSource = dataSource // 手动监听查询快照,处理空状态 targetCollection.addSnapshotListener { [weak self] snapshot, error in guard let self = self else { return } if let error = error { print("数据监听出错:\(error.localizedDescription)") return } let hasData = snapshot?.documents.count ?? 0 > 0 // 控制空视图和列表的显示/隐藏 self.emptyStateView.isHidden = hasData self.collectionView.isHidden = !hasData }
方法2:重写TableView/CollectionView的数据源计数方法
因为FirebaseUI的数据源已经实现了UITableViewDataSource或UICollectionViewDataSource协议,我们可以在ViewController里扩展这个协议,重写计数方法,在这里判断数据量并处理空视图:
针对UITableView的例子:
extension YourViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let dataCount = dataSource?.numberOfRows(in: section) ?? 0 // 配置空视图作为tableView的背景 let emptyView = self.setupEmptyView() tableView.backgroundView = dataCount == 0 ? emptyView : nil return dataCount } } // 自定义空视图的辅助方法 private func setupEmptyView() -> UIView { let emptyView = UIView(frame: tableView.bounds) let tipLabel = UILabel() tipLabel.text = "暂无数据,快来添加吧~" tipLabel.textAlignment = .center tipLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium) tipLabel.textColor = .gray emptyView.addSubview(tipLabel) tipLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tipLabel.centerXAnchor.constraint(equalTo: emptyView.centerXAnchor), tipLabel.centerYAnchor.constraint(equalTo: emptyView.centerYAnchor) ]) return emptyView }
针对UICollectionView的例子:
extension YourViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { let dataCount = dataSource?.numberOfItems(in: section) ?? 0 let emptyView = self.setupEmptyView() collectionView.backgroundView = dataCount == 0 ? emptyView : nil return dataCount } }
方法3:使用KVO监听数据源的items属性
FirebaseUI的数据源(比如FUITableViewDataSource、FUICollectionViewDataSource)内部有一个items数组存储当前数据,我们可以通过KVO监听这个属性的变化来判断空状态:
override func viewDidLoad() { super.viewDidLoad() // 初始化dataSource后添加KVO监听 dataSource.addObserver(self, forKeyPath: "items", options: [.initial, .new], context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == "items", let dataSource = object as? FUICollectionViewDataSource else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } let hasData = !(dataSource.items as? [Any] ?? []).isEmpty emptyStateView.isHidden = hasData collectionView.isHidden = !hasData } deinit { // 记得移除KVO监听,避免内存泄漏 dataSource.removeObserver(self, forKeyPath: "items") }
小提示
- 推荐优先使用方法1或方法2,方法1能更实时地响应数据变化,方法2则更贴合列表组件的生命周期;
- 空视图可以根据需求自定义,比如添加按钮、图标等,提升用户体验;
- 如果使用Firebase Realtime Database而非Firestore,思路是类似的,只需把查询监听换成Realtime Database的
observe(.value)方法即可。
内容的提问来源于stack exchange,提问作者Rohit
相关产品推荐
相关产品推荐

