- (void)videoPickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info
在iOS 13和其他iOS中返回不同的URL。
知道为什么会这样吗?
iOS 13:
file:///private/var/mobile/Containers/Data/PluginKitPlugin/0849234B-837C-43ED-BEDD-DE4F79E7CE96/tmp/trim.B8AB021D-F4B6-4E50-A93C-8B7F7FB40A1C.MOV
file:///private/var/mobile/Containers/Data/Application/5AE52A95-6A2F-49A5-8210-D70E022E9A05/tmp/5A8D81B5-FC42-4228-9514-CD998A4E7FA9.MOV
这是由于我没有PluginKitPlugin
文件夹的权限而导致的错误。
在两种情况下,我都是使用imagePicker
选择视频的。
答案 0 :(得分:5)
该问题可能与url的生存期有关,该生存期与NSDictionary<UIImagePickerControllerInfoKey,id> *)info
对象的生存期有关。如果对象被释放,则该URL无效。因此,您可以保留对对象的引用或将媒体复制到更永久的位置。在更新到iOS 13 / Xcode 11之后,我遇到了类似的问题。
注意:此答案也进行了修改,以符合@mstorsjo提供的信息,也在此线程中:https://stackoverflow.com/a/58099385/3220330
答案 1 :(得分:5)
我为此苦了几个晚上,终于解决了这个问题。
这里用例的差异之一是我将视频上传到AWS S3。这是通过后台线程中的S3传输实用程序发生的。经过一堆的试验和调试,这就是我的决定。
更改是在iOS 13中,图像选择器控制器didFinishPickingMediaWithInfo方法的info [ .mediaURL ]参数中返回的mediaURL指向“ PluginKitsPlugin ”目录。看来我们的应用很长时间无法访问此位置。
示例:file:/// private / var / mobile / Containers / Data / PluginKitPlugin / 0849234B-837C-43ED-BEDD-DE4F79E7CE96 / tmp / trim。 B8AB021D-F4B6-4E50-A93C-8B7F7FB40A1C.MOV
由于某些原因(也许有人知道),只能临时访问该URL。这里有一些理论建议关闭图像选择器控制器将取消分配URL,从而使其无效。
通过这种理论,我尝试解决这两种不同的方法:
最终解决此问题的方法是将信息[.mediaURL]复制到应用程序临时文件夹中的另一个位置。
这是我用来将信息[ .mediaURL ]复制到我应用的临时文件夹中的代码。
This function will copy a video file to a temporary location so that it remains accessbile for further handling such as an upload to S3.
- Parameter url: This is the url of the media item.
- Returns: Return a new URL for the local copy of the vidoe file.
*/
func createTemporaryURLforVideoFile(url: NSURL) -> NSURL {
/// Create the temporary directory.
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
/// create a temporary file for us to copy the video to.
let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent(url.lastPathComponent ?? "")
/// Attempt the copy.
do {
try FileManager().copyItem(at: url.absoluteURL!, to: temporaryFileURL)
} catch {
print("There was an error copying the video file to the temporary location.")
}
return temporaryFileURL as NSURL
}
此代码将文件复制到一个临时目录(如下所示),您的应用在其生命周期内可以访问该目录: 文件:/// private / var / mobile / Containers / Data / 应用程序/5AE52A95-6A2F-49A5-8210-D70E022E9A05/tmp/5A8D81B5-FC42-4228-9514-CD998A4E7FA9.MOV
您会注意到,选择要上传的图像(信息[ .imageURL ])将返回同一目录中的文件。上传图片没有先前的问题。
借助S3传输实用程序,可以在后台线程中访问文件并完成将视频上传到S3。
答案 2 :(得分:2)
扩展并阐明先前的答案。只要您要使用url,就需要保留对(NSDictionary<UIImagePickerControllerInfoKey,id> *)info
对象的引用。该词典包含对PHAsset对象的引用,该对象可能控制对URL的访问-在取消引用和释放资产对象之后,较早的URL将变得不可读。
此问题的其他解决方法是,将url复制到应用程序自己的沙箱中的另一个临时文件中,这可能是通过立即使用源url来工作的,尽管它仍然有效且可访问,但在发布信息和url之前再次无法访问。
答案 3 :(得分:2)
以下是code的Objective-C版本。最初的修复是由@Bumbleparrot快速给出的:
-(NSURL *)createTemporaryPathforVideoFile:(NSURL *)url{
NSURL *tempURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:true];
NSURL *tempFileURL = [tempURL URLByAppendingPathComponent:url.lastPathComponent];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager copyItemAtURL:url.absoluteURL toURL:tempFileURL error:nil];
return tempFileURL ;
}
答案 4 :(得分:0)
从我从具有此路径的iOS 13中遇到权限问题中收集的信息来看,这是因为选择器是一个单独的应用程序(具有自己的权限),在iOS 13中变得更加明确。因此,它给您的路径是在自己的临时目录(而不是您的应用程序)中。
对于我们来说,代码假定给定的路径是我们的临时目录。我切换到显式缓存到NSTemporaryDirectory。