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

调用FileManager.default.removeItem删除文件后设备存储空间未释放如何解决?

问题原因
  • 文件句柄未完全释放:如果删除视频时,该文件仍被播放器、文件读写流、AVAsset等实例持有,系统不会立刻回收存储空间,仅会移除文件目录入口,等所有持有句柄的对象销毁后才会真正释放空间。
  • 删除的是软链接/别名而非原文件:如果videoUrl是指向其他路径的软链接,删除链接不会影响原文件占用的空间。
  • 多副本存储:如果你导入视频时同时在沙盒、系统相册、应用缓存目录生成了多份副本,仅删除单份副本不会释放全部占用空间。
  • iCloud同步残留:如果文件存储在开启了iCloud同步的目录下,删除的文件会暂存在iCloud最近删除回收站保留30天,本地存储空间不会立刻释放。
  • 系统统计延迟:iOS的存储统计存在缓存,短时间内可能不会更新总可用空间,但该情况不会导致存储被永久占满。
修复方案

首先做问题定位:打印videoUrl.resolvingSymlinksInPath().path拿到文件真实路径,删除后再次判断该路径是否存在文件,确认原文件确实被移除。

代码修改如下:

  1. 先释放所有持有视频文件的对象,再执行删除
  2. 移除不必要的fileExists判断,避免竞态条件,直接捕获删除异常即可

修改后的代码示例:

private let fileManager = FileManager.default
func delete() throws {
    autoSave = nil
    // 第一步:先释放所有持有视频的相关实例,以下为播放器释放示例
    // 如果你有其他持有该视频的对象,需要在这一步全部释放/关闭
    if let player = currentPlayer {
        player.replaceCurrentItem(with: nil)
    }
    // 关闭所有正在读写该视频的FileHandle/输入输出流
    currentVideoFileHandle?.close()
    
    // 第二步:删除文件,无需提前判断存在性,直接捕获异常
    let dataUrl = recording.id.recordingFileUrl
    do {
        try fileManager.removeItem(at: dataUrl)
    } catch CocoaError.fileNoSuchFile {
        // 文件不存在,无需额外处理
    }
    
    let videoUrl = recording.videoUrl.resolvingSymlinksInPath()
    do {
        try fileManager.removeItem(at: videoUrl)
    } catch CocoaError.fileNoSuchFile {
        // 文件不存在,无需额外处理
    }
    
    // 可选:如果视频同时存储在系统相册,同步删除对应的PHAsset
    // 注意需要先获取PHPhotoLibrary操作权限
    /*
    PHPhotoLibrary.shared().performChanges {
        PHAssetChangeRequest.deleteAssets([yourPHAsset] as NSArray)
    } completionHandler: { success, error in
        // 处理删除结果
    }
    */
}

如果确认是iCloud同步导致的空间未释放,可以在删除前先将文件移到应用废纸篓:

try videoUrl.setResourceValue(true, forKey: .isTrashedKey)

内容的提问来源于stack exchange,提问作者Thomas Wix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 02:15:08