如何将video(库中)转换为NSData? 在Swift中
我只是没有“信息”在Swift imagePickerController,所以我不知道如何获取url,并将其转换为数据发送到Web服务。
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL! var videoFileURL = videoDataURL.filePathURL var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)") }
Xcode 8.3•Swift 3.1
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) { let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! if let fileURL = info[UIImagePickerControllerMediaURL] as? URL { do { try FileManager.default.moveItem(at: fileURL, to: documentsDirectoryURL.appendingPathComponent("videoName.mov") print("movie saved") } catch { print(error) } } }
Swift 2
你应该使用,如果让解开你的select权。 NSData.dataWithContentsOfMappedFile
也被弃用iOS8。 尝试使用NSData方法初始化器contentsOfURL:
注意:您还需要将didFinishPickingMediaWithInfo声明从[NSObject : AnyObject]
更改为[String : AnyObject]
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { if let fileURL = info[UIImagePickerControllerMediaURL] as? NSURL { if let videoData = NSData(contentsOfURL: fileURL) { print(videoData.length) } } }
正如Rob提到的那样,数据可能非常大,而不是复制文件,您应该将文件移动到文档文件夹中,如下所示:
let documentsDirectoryURL = try! NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true) if let fileURL = info[UIImagePickerControllerMediaURL] as? NSURL { do { try NSFileManagerdefaultManager().moveItemAtURL(fileURL, toURL: documentsDirectoryURL.URLByAppendingPathComponent("videoName").URLByAppendingPathExtension("mov")) print("movie saved") } catch { print(error) } }
有几个问题:
-
考虑这一行:
var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL!
这会强制展开
info[UIImagePickerControllerMediaURL]
(这很糟糕,因为如果它是nil
,应用程序会崩溃),并将其转换为隐式解包的可选NSURL!
。 这没有意义。 只要做一个有条件的解包(并解包到NSURL
,而不是NSURL!
):if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL { ... }
-
下一行调用
filePathURL
:var videoFileURL = videoDataURL.filePathURL
如果你想要一个文件的URL,你已经有一个,所以不需要转换,而是使用
videoDataURL
。 如果你真的想要一个path,你可以使用path
方法:let videoPath = videoDataURL.path
坦率地说,苹果公司试图将我们从使用stringpath,所以只使用原始的
videoDataURL
并避免使用path
和filePathURL
。 -
您正在使用
dataWithContentsOfMappedFile
:var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)")
如果你真的想使用
dataWithContentsOfMappedFile
,正确的Swift语法是:let video = NSData(contentsOfMappedFile: videoPath!)
但
dataWithContentsOfMappedFile
弃用,所以你应该使用:let video = try NSData(contentsOfFile: videoPath!, options: .DataReadingMappedIfSafe)
或者,完全绕过
videoPath
,您可以:let video3 = try NSData(contentsOfURL: videoDataURL, options: .DataReadingMappedIfSafe)
很明显,这些
try
引用应该在一个带有catch
块的do
块中完成。 -
顺便说一下,正如你在上面的例子中所看到的,应该尽可能地使用
let
。
–
坦率地说,我build议不要把它加载到NSData
中。 只要将它复制到NSFileManager
,这是一个更有效的内存使用。 如果video很长,可能会很大,并且应该避免在任何时间将整个内容加载到内存中。
所以你可以:
if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL { do { // build your destination URL however you want // // let tempFolder = NSURL(fileURLWithPath: NSTemporaryDirectory()) // let destinationURL = tempFolder.URLByAppendingPathComponent("test.mov") // or let documents = try NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false) let destinationURL = documents.URLByAppendingPathComponent("test.mov") // but just copy from the video URL to the destination URL try NSFileManager.defaultManager().copyItemAtURL(videoDataURL, toURL: destinationURL) } catch { print(error) } }
如果你正在上传到一个Web服务,那么你可以使用NSURLSessionUploadTask
,使用文件或stream选项。 这个请求的构build是一个单独的问题,但是希望你有这样的想法:对于像照片或者特别是video这样的大型资源,如果可以避免的话,不要使用资源实例化NSData
。