调用FileManager.default.removeItem删除文件后设备存储空间未释放如何解决?
问题原因
- 文件句柄未完全释放:如果删除视频时,该文件仍被播放器、文件读写流、AVAsset等实例持有,系统不会立刻回收存储空间,仅会移除文件目录入口,等所有持有句柄的对象销毁后才会真正释放空间。
- 删除的是软链接/别名而非原文件:如果
videoUrl是指向其他路径的软链接,删除链接不会影响原文件占用的空间。 - 多副本存储:如果你导入视频时同时在沙盒、系统相册、应用缓存目录生成了多份副本,仅删除单份副本不会释放全部占用空间。
- iCloud同步残留:如果文件存储在开启了iCloud同步的目录下,删除的文件会暂存在iCloud最近删除回收站保留30天,本地存储空间不会立刻释放。
- 系统统计延迟:iOS的存储统计存在缓存,短时间内可能不会更新总可用空间,但该情况不会导致存储被永久占满。
修复方案
首先做问题定位:打印videoUrl.resolvingSymlinksInPath().path拿到文件真实路径,删除后再次判断该路径是否存在文件,确认原文件确实被移除。
代码修改如下:
- 先释放所有持有视频文件的对象,再执行删除
- 移除不必要的
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
相关产品推荐
相关产品推荐

