Swift 3:删除UserDefaults数据与TableView对应行的方案求助
解决TableView行删除与UserDefaults数据同步问题
我来帮你搞定这个删除录音记录的问题,先梳理下你现有代码里的几个核心问题:
- 文件路径错误:你删除文件时用了
indexPath.row - 1,但你的文件名是indexPath.row + 1(和cell显示的编号一致),这会导致删错文件或者找不到文件。 - UserDefaults操作错误:直接调用
removeObject(forKey: "myNumber")会把整个录音记录数组删掉,而不是删除选中的那一项,这就会导致所有记录都丢失,而不是只删选中的。 - 数据未同步更新:你没有更新存储在UserDefaults里的数组,也没有更新
numberOfRecords变量,这会导致TableView的数据和实际存储的数据不一致。 - 多余的reloadData:调用
tableView.deleteRows(at: [indexPath], with: .fade)之后不需要再调用reloadData(),deleteRows已经会自动更新UI,重复调用反而可能引发问题。
下面是修正后的完整代码,我会标注关键修改点:
// 建议把UserDefaults的key定义成常量,避免拼写错误 private let kMyNumberKey = "myNumber" var numberOfRecords: Int = 0 // 最好把记录数组作为实例变量,方便操作 var records: [String] = [] // 在viewDidLoad或者合适的地方初始化数据 override func viewDidLoad() { super.viewDidLoad() // 从UserDefaults加载数据 records = UserDefaults.standard.stringArray(forKey: kMyNumberKey) ?? [] numberOfRecords = records.count tableView.reloadData() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return numberOfRecords } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = String(indexPath.row + 1) return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let path = getDiretory().appendingPathComponent("\(indexPath.row + 1).m4a") do { audioPlayer = try AVAudioPlayer(contentsOf: path) audioPlayer.play() } catch { print("播放失败:\(error.localizedDescription)") audioPlayer?.stop() } } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // 1. 先删除对应的录音文件 let fileName = "\(indexPath.row + 1).m4a" let fileURL = getDiretory().appendingPathComponent(fileName) do { try FileManager.default.removeItem(at: fileURL) } catch { print("删除文件失败:\(error.localizedDescription)") } // 2. 删除数组中对应的元素 records.remove(at: indexPath.row) // 3. 更新UserDefaults的数据 UserDefaults.standard.set(records, forKey: kMyNumberKey) // 4. 更新记录数量 numberOfRecords = records.count // 5. 删除TableView的行 tableView.deleteRows(at: [indexPath], with: .fade) // 这里不需要reloadData,deleteRows已经会更新UI } }
额外的几个小建议:
- 把UserDefaults的key定义成常量,避免拼写错误,也方便后续维护。
- 把记录数组作为实例变量保存,不要每次都从UserDefaults读取,这样操作更高效,也避免重复解析。
- 增加错误处理的打印,方便调试时排查问题(比如删除文件失败的原因)。
- 确保
getDiretory()方法是正确获取录音文件存储目录的,这个如果有问题也会导致文件删除失败。
内容的提问来源于stack exchange,提问作者George Copeland
相关产品推荐
相关产品推荐

