如何清空TableView并重新加载数据?解决重复显示问题
解决CollectionView重复显示数据的问题
我帮你分析下问题所在,然后给出具体的修复方案:
问题根源
你现在遇到的重复显示问题,主要来自两个点:
- 重复绑定Firebase监听:每次点击按钮调用
getWallpaperFromDB()时,都会新增一个childAdded类型的持续观察者——之前的监听并没有被移除,所以后续只要有数据触发,所有存在的观察者都会执行闭包,导致数据被多次添加到数组里。 - 数据源未清空:每次调用函数时,你直接往
wallpapers数组追加新数据,旧数据还留在数组里,自然会导致CollectionView重复渲染。
解决方案
针对这两个问题,我给你两种不同场景的修复方案:
场景一:只需要一次性加载数据(不需要实时监听更新)
如果你的需求是点击按钮后一次性拉取所有壁纸数据,不需要实时监听数据库的新增内容,可以改用observeSingleEvent单次监听,同时每次加载前清空数据源:
func getWallpaperFromDB() { let databaseRef = Database.database().reference() // 先清空数据源,避免旧数据残留 self.wallpapers.removeAll() // 使用单次监听获取所有壁纸数据 databaseRef.child("wallpapers").observeSingleEvent(of: .value) { snapshot in // 遍历所有子节点解析数据 for childSnapshot in snapshot.children { guard let childSnap = childSnapshot as? DataSnapshot, let value = childSnap.value as? [String: Any], let categoryID = value["categoryID"] as? String, let categoryName = value["categoryName"] as? String, let wallpaperName = value["wallpaperName"] as? String else { // 数据格式异常时跳过该节点,避免崩溃 continue } let wallpaperId = childSnap.key let dbWallpaper = Wallpaper(categoryID: categoryID, categoryName: categoryName, wallpaperId: wallpaperId, wallpaperName: wallpaperName) self.wallpapers.append(dbWallpaper) } // 遍历完成后统一刷新CollectionView self.collectionViewTable.reloadData() } } @IBAction func slideMenuButton(_ sender: Any) { getWallpaperFromDB() }
场景二:需要实时监听数据库的新增数据
如果你需要持续监听数据库里的新增壁纸,那么需要管理好观察者的引用,避免重复绑定:
首先在类中添加一个观察者引用属性:
// 保存壁纸监听的引用,用于后续移除 var wallpaperObserver: DatabaseHandle?
然后修改getWallpaperFromDB()函数:
func getWallpaperFromDB() { let databaseRef = Database.database().reference().child("wallpapers") // 移除旧的监听(如果存在),避免重复触发 if let observer = wallpaperObserver { databaseRef.removeObserver(withHandle: observer) } // 清空数据源,重新加载 self.wallpapers.removeAll() // 绑定新的监听并保存引用 wallpaperObserver = databaseRef.observe(DataEventType.childAdded) { snapshot in guard let value = snapshot.value as? [String: Any], let categoryID = value["categoryID"] as? String, let categoryName = value["categoryName"] as? String, let wallpaperName = value["wallpaperName"] as? String else { return } let wallpaperId = snapshot.key let dbWallpaper = Wallpaper(categoryID: categoryID, categoryName: categoryName, wallpaperId: wallpaperId, wallpaperName: wallpaperName) self.wallpapers.append(dbWallpaper) self.collectionViewTable.reloadData() } } @IBAction func slideMenuButton(_ sender: Any) { getWallpaperFromDB() }
另外补充个小建议:把代码里的强制解包(as!)换成可选绑定,能避免因为数据库数据格式异常导致的崩溃,就像上面代码里写的那样。
内容的提问来源于stack exchange,提问作者Sadi Hakan
相关产品推荐
相关产品推荐

