SwiftUI中PHPicker选取视频后VideoPlayer无法播放问题
问题定位
你的代码存在3个直接导致播放失败的问题:
- 播放逻辑存在低级语法错误:
VideoPlayer初始化时传入的是URL类型本身,而非你解包得到的实际路径变量,AVPlayer初始化时根本没有拿到有效资源地址。 - 缺失相册资源安全权限处理:PHPicker返回的视频URL是系统安全域限制的临时URL,直接调用
FileManager执行拷贝操作会因为权限不足失败,你用try?静默吞掉了所有拷贝错误,完全没有感知到文件根本没有复制到临时目录。 - 强制修改文件后缀:你给所有选中的视频强制拼接
.mp4后缀,但系统相册内的视频可能是mov、m4v等其他封装格式,后缀和实际文件格式不匹配也会导致播放失败。
修复方案
1. 修正PHPicker视频选取、拷贝逻辑
不要直接拿返回的URL做文件操作,先申请安全域访问权限,保留原文件后缀,不要吞掉文件操作的错误:
注意:使用
UTType做资源类型校验需要在文件顶部引入依赖:import UniformTypeIdentifiers
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard let pickResult = results.first else { return } // 校验资源是否为视频类型 guard pickResult.itemProvider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) else { return } pickResult.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { [weak self] originURL, loadError in guard let self = self, loadError == nil, let sourceURL = originURL else { debugPrint("视频资源加载失败:\(loadError?.localizedDescription ?? "未知错误")") return } // 申请安全作用域访问权限 guard sourceURL.startAccessingSecurityScopedResource() else { debugPrint("相册资源访问权限获取失败") return } // 作用域结束后自动释放权限 defer { sourceURL.stopAccessingSecurityScopedResource() } DispatchQueue.main.async { do { let fileID = UUID().uuidString // 保留原始文件后缀,不要强制指定mp4 let pathExt = sourceURL.pathExtension let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()) .appendingPathComponent(fileID) .appendingPathExtension(pathExt) // 临时路径存在同名文件先删除,避免拷贝报错 if FileManager.default.fileExists(atPath: targetURL.path) { try FileManager.default.removeItem(at: targetURL) } // 执行拷贝,捕获错误 try FileManager.default.copyItem(at: sourceURL, to: targetURL) // 将有效URL同步给视图模型 self.providerRoomSummitViewModel.roomIntroVideoURL = targetURL } catch { debugPrint("视频拷贝到临时目录失败:\(error.localizedDescription)") } } } }
2. 修正VideoPlayer调用代码
传入解包得到的实际URL变量,而非URL类型本身:
if let playableURL = providerRoomSummitViewModel.roomIntroVideoURL { VideoPlayer(player: AVPlayer(url: playableURL)) .frame(height: 280) // 根据页面需求设置播放器高度 }
开发提示:文件读写、权限类操作不要用
try?静默忽略错误,通过do-catch打印错误信息可以快速定位90%以上的路径、权限、文件冲突问题。临时目录的文件会在系统存储空间不足时被自动清理,无需手动删除;如果需要长期保存选中的视频,可以将文件拷贝到应用沙盒的Documents或Library目录下。
内容的提问来源于stack exchange,提问作者kuan
相关产品推荐
相关产品推荐

