imagePickerController:保存视频以在应用的后续 运行 中再次播放
imagePickerController: Save video to play again on a subsequent run of the app
在我的应用中,用户使用内置 UIImagePickerController
从他们的库中选择一个视频。我可以检索 URL 并播放所选视频。这很好用。
但是,我还希望能够在用户退出并重新启动应用程序后稍后播放同一视频,而无需用户使用选择器重新选择它。我想不出办法做到这一点。我尝试同时使用 UIImagePickerControllerReferenceURL
和 UIImagePickerControllerMediaURL
。当我立即播放视频时,它们都有效。我尝试将这些 URL 保存在 userDefaults
中,并在下次 运行 应用程序时检索它们。我正确检索了 URL,但视频无法使用 AVPlayer 播放。我预计 UIImagePickerControllerMediaURL
会出现这种行为,因为这似乎是暂时的 URL,但我没想到 UIImagePickerControllerReferenceURL
.
会出现这种情况
我也尝试过使用 PHAsset.fetchAssets(withALAssetURLs: <#T##[URL]#>, options: <#T##PHFetchOptions?#>)
但这没有 return 任何值。
如何保存对视频的引用或视频本身供以后使用?
试试这个方法,对我有用:
private func loadVideo(url: URL, saveUrl: Bool = false) {
let player = AVPlayer(url: url)
let playerController = AVPlayerViewController()
playerController.player = player
present(playerController, animated: true) {
player.play()
}
guard saveUrl else { return }
UserDefaults.standard.set(url, forKey: "keyVideoUrl")
UserDefaults.standard.synchronize()
}
要按顺序获得权限,请在 Info.plist
文件中添加以下内容:
<key>NSPhotoLibraryUsageDescription</key>
<string>Message description in here</string>
现在请求许可并启动视频选择器:
PHPhotoLibrary.requestAuthorization { [weak self] (status) -> Void in
guard status == .authorized else { return }
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.mediaTypes = [kUTTypeMovie as String]
self?.present(imagePicker, animated: true, completion: nil)
}
终于使用这个didFinishPickingMediaWithInfo
方法:
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
self.dismiss(animated: true, completion: nil)
guard let asset = info[UIImagePickerControllerPHAsset] as? PHAsset else { return }
PHImageManager.default().requestAVAsset(forVideo: asset, options: PHVideoRequestOptions(),
resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
if let urlAsset = asset as? AVURLAsset {
self.loadVideo(url: urlAsset.url, saveUrl: true)
}
})
}
}
选择视频并播放后,您可以重新启动应用并尝试重播,如下所示:
if let url = UserDefaults.standard.url(forKey: "keyVideoUrl") {
self.loadVideo(url: url)
}
这是完整的工作源代码ViewController.swift
感谢AamirR 和Max9xs 对我上述问题的评论,我选择实施的解决方案是将文件从TMP 目录移动到Documents 目录。然后播放 Documents 目录中的视频。这也避免了每次用户使用 imagePickerController 选择新视频时 TMP 目录都被视频填满的问题。
委托函数中的以下代码将移动文件:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let mediaType = info[UIImagePickerControllerMediaType] as! String
if mediaType == (kUTTypeMovie as String) {
let TMPvideoURL = info[UIImagePickerControllerMediaURL] as! URL
let TMPvideoPath = TMPvideoURL.path
let manager = FileManager.default
let documentsDirectory = manager.urls(for: .documentDirectory, in: .userDomainMask).last!
let docVideoURL = documentsDirectory.appendingPathComponent("selectedLibraryVideo.mov")
let docVideoPath = docVideoURL.path
do {
if manager.fileExists(atPath: docVideoPath) {
try manager.removeItem(atPath: docVideoPath)
}
try manager.moveItem(atPath: TMPvideoPath, toPath: docVideoPath)
}
catch {
print(error)
}
}
photoLibraryPickerController?.dismiss(animated: false, completion: nil)
}
然后我可以通过引用 Documents 文件夹中的文件路径来播放视频。这很好用。
let documentsDirectory = manager.urls(for: .documentDirectory, in: .userDomainMask).last!
let docVideoURL = documentsDirectory.appendingPathComponent("selectedLibraryVideo.mov")
let docVideoPath = docVideoURL.path
在我的应用中,用户使用内置 UIImagePickerController
从他们的库中选择一个视频。我可以检索 URL 并播放所选视频。这很好用。
但是,我还希望能够在用户退出并重新启动应用程序后稍后播放同一视频,而无需用户使用选择器重新选择它。我想不出办法做到这一点。我尝试同时使用 UIImagePickerControllerReferenceURL
和 UIImagePickerControllerMediaURL
。当我立即播放视频时,它们都有效。我尝试将这些 URL 保存在 userDefaults
中,并在下次 运行 应用程序时检索它们。我正确检索了 URL,但视频无法使用 AVPlayer 播放。我预计 UIImagePickerControllerMediaURL
会出现这种行为,因为这似乎是暂时的 URL,但我没想到 UIImagePickerControllerReferenceURL
.
我也尝试过使用 PHAsset.fetchAssets(withALAssetURLs: <#T##[URL]#>, options: <#T##PHFetchOptions?#>)
但这没有 return 任何值。
如何保存对视频的引用或视频本身供以后使用?
试试这个方法,对我有用:
private func loadVideo(url: URL, saveUrl: Bool = false) {
let player = AVPlayer(url: url)
let playerController = AVPlayerViewController()
playerController.player = player
present(playerController, animated: true) {
player.play()
}
guard saveUrl else { return }
UserDefaults.standard.set(url, forKey: "keyVideoUrl")
UserDefaults.standard.synchronize()
}
要按顺序获得权限,请在 Info.plist
文件中添加以下内容:
<key>NSPhotoLibraryUsageDescription</key>
<string>Message description in here</string>
现在请求许可并启动视频选择器:
PHPhotoLibrary.requestAuthorization { [weak self] (status) -> Void in
guard status == .authorized else { return }
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.mediaTypes = [kUTTypeMovie as String]
self?.present(imagePicker, animated: true, completion: nil)
}
终于使用这个didFinishPickingMediaWithInfo
方法:
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
self.dismiss(animated: true, completion: nil)
guard let asset = info[UIImagePickerControllerPHAsset] as? PHAsset else { return }
PHImageManager.default().requestAVAsset(forVideo: asset, options: PHVideoRequestOptions(),
resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
if let urlAsset = asset as? AVURLAsset {
self.loadVideo(url: urlAsset.url, saveUrl: true)
}
})
}
}
选择视频并播放后,您可以重新启动应用并尝试重播,如下所示:
if let url = UserDefaults.standard.url(forKey: "keyVideoUrl") {
self.loadVideo(url: url)
}
这是完整的工作源代码ViewController.swift
感谢AamirR 和Max9xs 对我上述问题的评论,我选择实施的解决方案是将文件从TMP 目录移动到Documents 目录。然后播放 Documents 目录中的视频。这也避免了每次用户使用 imagePickerController 选择新视频时 TMP 目录都被视频填满的问题。
委托函数中的以下代码将移动文件:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let mediaType = info[UIImagePickerControllerMediaType] as! String
if mediaType == (kUTTypeMovie as String) {
let TMPvideoURL = info[UIImagePickerControllerMediaURL] as! URL
let TMPvideoPath = TMPvideoURL.path
let manager = FileManager.default
let documentsDirectory = manager.urls(for: .documentDirectory, in: .userDomainMask).last!
let docVideoURL = documentsDirectory.appendingPathComponent("selectedLibraryVideo.mov")
let docVideoPath = docVideoURL.path
do {
if manager.fileExists(atPath: docVideoPath) {
try manager.removeItem(atPath: docVideoPath)
}
try manager.moveItem(atPath: TMPvideoPath, toPath: docVideoPath)
}
catch {
print(error)
}
}
photoLibraryPickerController?.dismiss(animated: false, completion: nil)
}
然后我可以通过引用 Documents 文件夹中的文件路径来播放视频。这很好用。
let documentsDirectory = manager.urls(for: .documentDirectory, in: .userDomainMask).last!
let docVideoURL = documentsDirectory.appendingPathComponent("selectedLibraryVideo.mov")
let docVideoPath = docVideoURL.path