UITableView删除单元格未消失却被剩余单元格复制替换问题求助
问题修复方案
核心错误原因
你的猜测并不正确,numberOfRowsInSection是动态返回spotsList的长度,不需要手动修改赋值。问题实际出在以下两处逻辑:
- Firebase的
.value监听回调中,每次收到数据快照时直接向spotsList追加元素,没有先清空旧数据。删除操作触发数据库更新后,回调会将剩余的有效数据再次追加到原有数组中,导致数组存在重复元素,表现为单元格被拷贝。 - 删除逻辑中
reloadData调用时机混乱:你在removeValue的异步回调外部提前调用了reloadData,此时本地数组还未修改、数据库删除请求也未完成;同时回调中同时混用deleteRows和reloadData,反而会导致界面状态和数据源不同步。
修复后代码
import UIKit import Firebase import FirebaseAuth class SpotRemove: ViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tblSpots: UITableView! var spotsList = [ArtistModel]() var refSpots: DatabaseReference? public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return spotsList.count } public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell let spot = spotsList[indexPath.row] cell.lblName.text = spot.type cell.lblGenre.text = spot.avail cell.lblPrice.text = spot.price return cell } override func viewDidLoad() { super.viewDidLoad() tblSpots.allowsMultipleSelectionDuringEditing = true refSpots = Database.database().reference().child("Spots") refSpots?.observe(.value, with: { [weak self] (snapshot) in guard let self = self else { return } // 先清空旧数据源,再添加新数据 self.spotsList.removeAll() if snapshot.childrenCount > 0 { let userID = Auth.auth().currentUser?.uid for spots in snapshot.children.allObjects as! [DataSnapshot] { let spotKey = spots.key let spotObject = spots.value as? [String: AnyObject] let spotType = spotObject?["Type"] let spotAvail = spotObject?["Availability"] let spotPrice = spotObject?["Price"] let spotID = spotObject?["UserID"] let spot = ArtistModel(id: spotID as! String?, avail: spotAvail as! String?, type: spotType as! String?, price: spotPrice as! String?, key: spotKey as! String?) if userID == spotID as? String { self.spotsList.append(spot) } } } // 无数据时也需要刷新界面,UI操作统一调度到主队列 DispatchQueue.main.async { self.tblSpots.reloadData() } }) } func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return true } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { guard editingStyle == .delete else { return } let spot = self.spotsList[indexPath.row] guard let spotKey = spot.key else { return } Database.database().reference().child("Spots").child(spotKey).removeValue { (error, ref) in if let error = error { print("Failed to delete message:", error) return } // 此处不需要手动修改数组和刷新界面,Firebase的监听回调会自动更新数据源并刷新 } } }
补充说明
修复后删除操作触发后,Firebase的监听会自动收到更新后的数据,清空旧数组重新加载后刷新界面,不会再出现重复单元格的问题。如果需要保留删除动画,也可以在删除回调中手动更新本地数组和界面,此时只要避免deleteRows和reloadData混用即可。
内容的提问来源于stack exchange,提问作者jspiezio
相关产品推荐
相关产品推荐

