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

FileManager .removeItem(at:)无完成回调,如何判断文件删除完成以更新列表?

根本原因

你的崩溃和文件删除逻辑无关,removeItem(at:) 确实是同步接口,执行完成时文件已经被实际删除。
从崩溃堆栈可以看出,问题出在 SwiftUI 内部的 List 数据源状态不匹配:onDelete 回调执行时,SwiftUI 默认期望你对数据源数组做局部删除操作(即删除对应索引的元素),你直接调用 updateURLs() 全量替换了整个数据源数组,导致 List 内部维护的编辑状态和实际数据源不一致,触发了 SwiftUI 内部断言崩溃。你加的延迟能生效,本质是等 onDelete 对应的编辑生命周期完全结束后才更新数据源,避免了状态冲突。

解决方案

方案1:优先适配 List 编辑规则(推荐)

先局部更新数据源满足 SwiftUI 的编辑预期,再执行文件删除操作,最后异步全量同步数据源保证准确性:

.onDelete { row in
    guard let i = row.first, let fileURL = urls[safe: i] else { return }
    // 先移除数据源对应元素,匹配List编辑预期
    urls.remove(at: i)
    do {
        try FileManager.default.removeItem(at: fileURL)
        // 异步全量同步,避免和当前编辑流程冲突
        DispatchQueue.main.async {
            updateURLs()
        }
    } catch { 
        print(error.localizedDescription)
        // 文件删除失败时回滚数据源
        urls.insert(fileURL, at: i)
    }
}

方案2:异步更新数据源

如果不想修改现有逻辑,只需要把 updateURLs() 包在主队列异步调用里即可,不需要固定时长延迟:

try FileManager.default.removeItem(at: fileURL)
DispatchQueue.main.async {
    updateURLs()
}

主队列是串行执行的,async 提交的任务会等当前 onDelete 编辑流程完全结束后再执行,不会产生状态冲突,也没有多余的等待时间。

内容的提问来源于stack exchange,提问作者LinusG.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 07:57:04