使用PHPickerViewController读取视频时报public.video类型加载错误如何解决
问题原因与解决方案
- 第一步:检查PHPicker初始化的过滤配置
绝大多数该报错是因为初始化选择器时没有正确指定视频类型过滤,导致返回结果内的itemProvider不包含视频类型的表示,另外必须导入UniformTypeIdentifiers框架,否则UTType会识别异常,正确初始化代码如下:import UniformTypeIdentifiers // 初始化PHPicker的代码 var config = PHPickerConfiguration() config.filter = .videos // 仅选择视频用该配置,需要图文混选可替换为.any(of: [.images, .videos]) config.selectionLimit = 1 // 单选设为1,多选按实际需求调整 let picker = PHPickerViewController(configuration: config) picker.delegate = self present(picker, animated: true) - 第二步:优化代理方法逻辑,增加错误降级处理
原代码缺少类型校验,且没有处理系统临时URL自动回收的问题,iOS 15.0~15.3版本还存在loadFileRepresentation随机报错的已知系统bug,调整后的兼容代码如下:func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { dismiss(animated: true) guard let result = results.first, let itemProvider = result.itemProvider, itemProvider.hasItemConformingToTypeIdentifier(UTType.video.identifier) else { print("无有效视频资源") return } // 优先使用官方推荐的加载方式 itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.video.identifier) { [weak self] url, error in if let error = error { print("loadFileRepresentation失败: \(error)") // 出错自动走备选加载方案 self?.loadVideoByBackupMethod(itemProvider: itemProvider) return } guard let tempUrl = url else { self?.loadVideoByBackupMethod(itemProvider: itemProvider) return } // 系统返回的临时URL会在闭包结束后销毁,必须复制到自身沙盒目录留存 let destUrl = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString + ".mov") do { try FileManager.default.copyItem(at: tempUrl, to: destUrl) // 此处destUrl即为可用于上传Firebase Storage的稳定本地路径 print("视频路径获取成功:\(destUrl)") } catch { print("临时文件复制失败: \(error)") self?.loadVideoByBackupMethod(itemProvider: itemProvider) } } } // 备选加载方案,适配系统bug场景 private func loadVideoByBackupMethod(itemProvider: NSItemProvider) { itemProvider.loadItem(forTypeIdentifier: UTType.video.identifier, options: nil) { item, error in guard error == nil, let videoUrl = item as? URL else { print("视频加载失败,请重新选择") // 此处可弹出用户提示 return } do { let videoData = try Data(contentsOf: videoUrl) let destUrl = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString + ".mov") try videoData.write(to: destUrl) // 此处destUrl即为可用于上传Firebase Storage的稳定本地路径 print("备选方案获取视频路径成功:\(destUrl)") } catch { print("视频读取失败: \(error)") } } }
内容的提问来源于stack exchange,提问作者EAO123
相关产品推荐
相关产品推荐

