升级到Xcode 7后,UIImagePickerControllerMediaURL找不到文件

3
升级我的Swift视频应用程序到Swift 2.0 / Xcode 7 / iOS 9后,除了从UIImagePickerController获取视频外,一切正常。相机和库的所有权限都已经检查过了。我可以进入并记录新视频或从库中选择现有视频。但是,当调用委托方法imagePickerController:didFinishPickingMediaWithInfo时,NSFileManager告诉我在UIImagePickerControllerMediaURL上没有文件。这在调用dismissViewControllerAnimated之前和之后都是正确的。
在升级过程中,它之前一直运行得很好,并且没有进行任何主要的代码更改。我在网上没有找到其他类似的问题报告,因此我认为我一定搞砸了一些东西,比如文件夹权限,但我无法弄清楚。我认为使用NSAppTransportSecurity可能与此有关,因为它涉及file:/// URL,但是无论我的info.plist中是否存在该字典,该问题在iOS 7、8和9中仍然存在。
如果有人能给我一些线索,我将非常感激。我已经在iPhone 6、5s和4s上尝试了这个问题,结果都是一样的。我记得在Swift 2升级期间一直困扰着“kUTTypeMovie”。下面的“[kUTTypeMovie as String]”是我找到的Xcode会接受的唯一东西。这可能是一个弱点,但我怀疑它是否有效,因为它似乎按预期工作。我提到它的唯一原因是,如果您不请求类型,则应用程序没有权限接收它。
额外信息:
我能够像往常一样使用UIImagePickerController从相机/库中获取图像。我突发奇想,以为我可以通过只获取原始视频并自己压缩来避免此问题,但NSFileManager告诉我在UIImagePickerControllerReferenceURL上也没有文件。我不知道除非我的应用程序被拒绝访问,否则这可能是如何实现的。
以下是相关代码:
 @IBAction func actionTakeVideo(sender: AnyObject) {
    if videoPickerController == nil {
        videoPickerController = UIImagePickerController()
        videoPickerController.delegate = self
        videoPickerController.mediaTypes = [kUTTypeMovie as String]
        videoPickerController.videoMaximumDuration = NSTimeInterval(maxVideoDuration-1)
        videoPickerController.allowsEditing = true
        videoPickerController.videoQuality = UIImagePickerControllerQualityType.TypeHigh
 }

...

// From Library
       let status:ALAuthorizationStatus = ALAssetsLibrary.authorizationStatus()
       if status != ALAuthorizationStatus.Authorized{
           print("Library not authorized: status != ALAuthorizationStatus.Authorized")
       } else {
           self.videoPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
           self.presentViewController(self.videoPickerController, animated: true, completion: nil)
       }

...

//From Camera
      if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
            self.videoPickerController.sourceType = UIImagePickerControllerSourceType.Camera
            self.videoPickerController.cameraDevice = UIImagePickerControllerCameraDevice.Front
            self.presentViewController(self.videoPickerController, animated: true, completion: nil)
      } 

...

//Delegate
     func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
         let manager = NSFileManager.defaultManager();
         let videoURL = info[UIImagePickerControllerMediaURL] as! NSURL
         if manager.fileExistsAtPath(videoURL.absoluteString) {
             print("THERE IS a file at: \(videoURL.absoluteString)")
         } else {
             print("THERE IS NOT a file at: \(videoURL.absoluteString)") // ALWAYS LANDS HERE.
         }
     }

UIImagePickerControllerMediaURL 是一个类似于 file:///private/var/mobile/Containers/Data/Application/6754830D-ER98-31OL-GU34-78067GD908PI/tmp/trim.578E437C-EEBC-4BC5-AD5C-C351BD0822B2.MOV 的链接。


你遇到了什么错误? - Sohil R. Memon
没有抛出任何错误。问题的唯一证据是当我尝试访问视频文件时 - 什么也没有。如果有通知可以观察到UIImagePickerController内部压缩或文件传输过程中或其基础组件中捕获错误,我不知道它们。 - jbcaveman
你是否发现了为什么会这样?似乎在iOS 9 SDK中,键UIImagePickerControllerMediaURL不再存在。 - Marc-Alexandre Bérubé
1
我遇到了同样的问题。我确认UIImagePickerControllerMediaURL文件确实存在。使用IExplorer,我可以在设备上打开临时文件。本以为这可能是iOS 9中的声明性权限问题,但我找不到任何要添加到PLIST中以修复此问题的内容。我还使用NSInputStream来读取文件。它返回错误域= NSPOSIXErrorDomain代码= 2 "没有这样的文件或目录"。 - Dan Loughney
1
我仍在等待苹果公司回复我的漏洞报告。请在bugreport.apple.com上添加您自己的漏洞报告,以便他们能够解决此问题。谢谢。 - jbcaveman
显示剩余2条评论
1个回答

1

我知道这个问题很老了,但今天我也遇到了同样的错误。

问题在于你正在从videoURL.absoluteString获取文件URL字符串,并将其传递给NSFileManager的fileExistsAtPath方法,而不是路径。你应该通过读取NSURL的"path"属性来获取文件的路径。

从videoURL.absoluteString读取的文件URL看起来像这样:

file:///private/var/mobile/Containers/Data/Application/6754830D-ER98-31OL-GU34-78067GD908PI/tmp/trim.578E437C-EEBC-4BC5-AD5C-C351BD0822B2.MOV

从videoURL.path读取的文件路径将如下所示:

/private/var/mobile/Containers/Data/Application/6754830D-ER98-31OL-GU34-78067GD908PI/tmp/trim.578E437C-EEBC-4BC5-AD5C-C351BD0822B2.MOV

以下代码:
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
         let manager = NSFileManager.defaultManager();
         let videoURL = info[UIImagePickerControllerMediaURL] as! NSURL
         if manager.fileExistsAtPath(videoURL.absoluteString) {
             print("THERE IS a file at: \(videoURL.absoluteString)")
         } else {
             print("THERE IS NOT a file at: \(videoURL.absoluteString)") // ALWAYS LANDS HERE.
         }
     }

必须更改为:

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
         let manager = NSFileManager.defaultManager();
         let videoURL = info[UIImagePickerControllerMediaURL] as! NSURL
         if manager.fileExistsAtPath(videoURL.path) {
             print("THERE IS a file at: \(videoURL.path)")
         } else {
             print("THERE IS NOT a file at: \(videoURL.path)") // ALWAYS LANDS HERE.
         }
     }

请记住UIImagePickerControllerMediaURL可能不存在:

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
         if let videoURL = info[UIImagePickerControllerMediaURL] as? URL {
             if FileManager.default.fileExistsAtPath(videoURL.path) {
                 print("THERE IS a file at: \(videoURL.path)")
             } else {
                 print("THERE IS NOT a file at: \(videoURL.path)") // ALWAYS LANDS HERE.
             }
         }
     }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接