PHPickerViewController获取视频后复制文件是否必要?是否增加上传耗时?
关于PHPicker获取视频后复制文件代码的必要性分析
核心结论
你加的那行try! FileManager.default.copyItem(at: videoURL, to: copiedURLFile)不是必需的,但有它的存在逻辑:
- 它确实会增加上传总耗时(要完整复制一遍视频文件,长视频的耗时会更明显),甚至可能因为复制环节出错(比如磁盘空间不足、复制超时)导致报错;
- 原
videoURL指向的是系统临时目录里的文件,系统可能在loadFileRepresentation的回调结束后自动清理这个文件。如果Firebase的异步上传还没完成,文件就被删了,会导致上传失败——这就是教程里添加复制代码的原因。
两种优化方案
方案一:直接移除复制代码(推荐优先尝试)
能节省复制时间,还能避免复制环节的错误。只要Firebase上传任务在运行,系统一般不会立刻清理原临时文件,实际测试中大部分场景都能正常工作。
修改后的代码:
result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { videoURL, error in assert(Thread.isMainThread == false) if let videoURL = videoURL { DispatchQueue.main.async { observer.hasUploaded = true observer.uploadVideo(videoURL: videoURL, uid: self.uid!, fileID: self.fileID, progressWheel: self.progressWheel, errorLabel: self.errorLabel, progressView: self.progressView, progressLabel: self.progressLabel) print("upload started to the cloud") } } else { print(error!); print("video might be too long or failed to load") /*alert*/ } }
方案二:保留复制但修复错误处理
如果移除复制后出现上传失败(系统提前清理了临时文件),可以保留复制,但一定要换掉危险的try!——它会在复制出错时直接崩溃,换成do-catch捕获错误后可以给用户提示。
修改后的代码:
result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { videoURL, error in assert(Thread.isMainThread == false) let directory = NSTemporaryDirectory() let fileName = NSUUID().uuidString.appending(".mov") if let videoURL = videoURL, let copiedURLFile = NSURL.fileURL(withPathComponents: [directory, fileName]) { do { try FileManager.default.copyItem(at: videoURL, to: copiedURLFile) DispatchQueue.main.async { observer.hasUploaded = true observer.uploadVideo(videoURL: copiedURLFile, uid: self.uid!, fileID: self.fileID, progressWheel: self.progressWheel, errorLabel: self.errorLabel, progressView: self.progressView, progressLabel: self.progressLabel) print("upload started to the cloud") } } catch { print("Failed to copy video file: \(error)") // 这里可以添加弹窗提示用户复制失败,比如磁盘空间不足 } } else { print(error!); print("video might be too long or failed to load") /*alert*/ } }
额外建议
如果你的App支持iOS 14及以上,可以改用loadInPlaceFileRepresentation替代loadFileRepresentation——这个方法返回的文件不会被系统自动清理,不需要手动复制,能彻底解决这个问题。
内容的提问来源于stack exchange,提问作者EAO123
相关产品推荐
相关产品推荐

