我正在尝试弄清楚如何使用 PHPicker 加载视频。我知道如何处理图像,但我似乎不知道如何处理视频。此代码仅适用于某些视频,不适用于其他视频。
这是我的代码
struct MediaPicker: UIViewControllerRepresentable {
@Binding var video: URL?
typealias UIViewControllerType = PHPickerViewController
class Coordinator: NSObject, PHPickerViewControllerDelegate {
var parent: MediaPicker
init(_ parent: MediaPicker) {
self.parent = parent
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
if results.isEmpty {
picker.dismiss(animated: true)
return
}
let provider = results.first!.itemProvider
if provider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) {
provider.loadItem(forTypeIdentifier: UTType.movie.identifier) { url, err in
if err != nil {return}
if let url = url {
DispatchQueue.main.sync {
self.parent.video = url as! URL?
picker.dismiss(animated: true)
}
}
}
}
}
}
func makeUIViewController(context: Context) -> PHPickerViewController {
var configuration = PHPickerConfiguration()
configuration.preferredAssetRepresentationMode = .automatic
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
}
func makeCoordinator() -> Coordinator {
return MediaPicker.Coordinator(self)
}
}
首先请设置
preferredAssetRepresentationMode = .current
- 选择视频后它将删除解码(对我来说,每个视频需要几秒钟的时间来解码 - 不可接受)。
其次,您需要将文件复制到临时文件夹,因为关闭后,所选文件将被删除,您将无法使用它。来自文档:
此方法将文件数据的副本写入临时文件,系统在完成处理程序返回时删除该文件。
看看我为案例编写的带有视频的代码:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
itemProviders = results.map(\.itemProvider)
itemProviders.forEach {
guard let typeIdentifier = $0.registeredTypeIdentifiers.first,
let utType = UTType(typeIdentifier) else { return }
if utType.conforms(to: .movie) {
var videoName = ""
if let suggestedName = $0.suggestedName {
if utType.conforms(to: .mpeg4Movie) {
videoName = suggestedName + ".mp4"
} else {
videoName = suggestedName + ".mov"
}
}
let group = DispatchGroup()
group.enter()
$0.loadFileRepresentation(forTypeIdentifier: typeIdentifier) { [weak self] url, error in
guard let self, let url else { return }
if let error {
print(error.localizedDescription)
}
// copying file
let fm = FileManager.default
let destination = fm.temporaryDirectory.appendingPathComponent(videoName)
do {
try fm.copyItem(at: url, to: destination)
} catch {
print(error.localizedDescription)
}
group.leave()
group.notify(queue: DispatchQueue.global()) {
// do staff with video
self.output.videoIsPicked(url: destination)
}
}
}
}