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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:09:33