You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:42:53