如何在Firebase的onChildRemoved方法中删除UITableView对应单元格
解决Firebase删除数据后UITableView未更新的问题
看起来你遇到的问题是从Firebase删除用户关联的课程后,UITableView里的旧数据还没消失。核心问题有两个:一是你在childAdded里监听class_info用了.value事件(会重复触发导致数组重复添加),二是childRemoved里没正确找到要删除的数据并更新表格。我帮你一步步解决:
第一步:修正childAdded里的重复添加问题
你现在在获取class_id后,用observe(DataEventType.value)监听class_info,这会导致每次class_info的数据变化时都会执行闭包,重复把同一个Class对象添加到classes2数组里。应该换成observeSingleEvent(.value),这样只获取一次数据,避免重复:
Database.database().reference().child("Classes").child(class_id!) .child("class_info").observeSingleEvent(of: .value, with: { (snapshot) in print("2.5",snapshot) let postDict = snapshot.value as? [String : AnyObject] ?? [:] print("3", postDict) let class_object = Class(dictionary: postDict) // 先判断数组里有没有这个class_id的对象,避免重复添加(可选但推荐) if !self.classes2.contains(where: { $0.class_id == class_object.class_id }) { self.classes2.append(class_object) DispatchQueue.main.async { self.tb_Yourclasses.reloadData() } } }, withCancel: nil)
第二步:完善childRemoved的逻辑
当触发.childRemoved时,你拿到了被删除的class_id,接下来需要:
- 在
classes2数组中找到对应class_id的元素 - 移除该元素
- 在主线程更新UITableView(用删除动画比直接reload更友好)
修改后的childRemoved闭包代码:
Database.database().reference().child("Users").child(userID).child("Classes").observe(.childRemoved, with: { (snapshot) in guard let deletedClassId = snapshot.value as? String else { return } // 找到数组中对应class_id的元素的索引 if let index = self.classes2.firstIndex(where: { $0.class_id == deletedClassId }) { // 在主线程更新UI DispatchQueue.main.async { // 移除数组元素并删除表格单元格 self.classes2.remove(at: index) self.tb_Yourclasses.deleteRows(at: [IndexPath(row: index, section: 0)], with: .automatic) } } })
额外注意点
- 确保你的
Class模型里的class_id属性正确映射自Firebase的uid字段(看你的数据库结构,class_info里的uid就是课程ID),这样才能匹配到要删除的元素。 - 所有UI操作(比如更新表格)必须放在
DispatchQueue.main.async里,因为Firebase的回调是在后台线程执行的。
修改后的完整fetchClass2函数
func fetchClass2(){ guard let userID = Auth.auth().currentUser?.uid else { print("用户未登录") return } print(userID) // 监听课程添加 Database.database().reference().child("Users").child(userID).child("Classes").observe(.childAdded, with: { (snapshot) in print("1",snapshot) guard let class_id = snapshot.value as? String else { return } print("2",class_id) Database.database().reference().child("Classes").child(class_id).child("class_info").observeSingleEvent(of: .value, with: { (snapshot) in print("2.5",snapshot) let postDict = snapshot.value as? [String : AnyObject] ?? [:] print("3", postDict) let class_object = Class(dictionary: postDict) // 避免重复添加 if !self.classes2.contains(where: { $0.class_id == class_object.class_id }) { self.classes2.append(class_object) DispatchQueue.main.async { self.tb_Yourclasses.reloadData() } } }, withCancel: nil) }, withCancel: nil) // 监听课程删除 Database.database().reference().child("Users").child(userID).child("Classes").observe(.childRemoved, with: { (snapshot) in guard let deletedClassId = snapshot.value as? String else { return } if let index = self.classes2.firstIndex(where: { $0.class_id == deletedClassId }) { DispatchQueue.main.async { self.classes2.remove(at: index) self.tb_Yourclasses.deleteRows(at: [IndexPath(row: index, section: 0)], with: .automatic) } } }) }
这样修改后,当你从Firebase删除用户的课程关联时,UITableView会自动删除对应的单元格,而且不会有重复数据的问题。
内容的提问来源于stack exchange,提问作者Samuel
相关产品推荐
相关产品推荐

