【问题标题】:converting video to NSData in share extension in ios在 ios 的共享扩展中将视频转换为 NSData
【发布时间】:2017-01-03 11:33:50
【问题描述】:

我为我的 ios 应用创建了一个共享扩展。当我单击照片应用程序中的共享选项时,会显示我的共享扩展名,然后单击它并显示我的控制器。一切都很好。我正在使用 youtube api 将视频上传到 youtube。我正在使用这种方法来创建参数

GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:fileData MIMEType:@"video/*"];

现在,如果视频很小,则可以使用此代码轻松将其转换为 NSData

NSData *fileData = [NSData dataWithContentsOfURL:[NSURL URLWithString:videoURL]];

一切正常,视频已上传。

但是如果视频很大,那么它只会崩溃并退出共享扩展(我设置了断点并发现了这个问题。如果我删除了 fileData 转换,那么它不会崩溃。)。所以我所做的不是将其转换为 NSData 我使用了这个 youtube api 方法

GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithFileURL:[NSURL URLWithString:videoURL] MIMEType:@"video/*"];

现在应用程序没有崩溃,但出现网络错误。错误是

错误域=NSURLErrorDomain Code=-995 "(null)"

小搜索发现是因为NSURLSession,被告知要使用这样的东西

sessionConfiguration.sharedContainerIdentifier = @“com.me.myapp.containerIdentifier”;

我正在使用 youtube api。我不确定在哪里使用它,或者是否有任何其他方式可以在大型视频文件的共享扩展中使用 youtube api。

注意:我在我的应用程序中使用了 youtube api,它与 NSData 一起工作正常。

希望问题很清楚。我现在坚持了一天。请帮忙。

提前致谢。

编辑 1:

我用过这段代码

NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoURL] options:0 error:&error];

文件数据为零。我得到的错误是

错误域=NSCocoaErrorDomain 代码=260 "文件“IMG_2187.MOV” 无法打开,因为没有这样的文件。” UserInfo={NSFilePath=/file:/var/mobile/Media/DCIM/102APPLE/IMG_2187.MOV,

【问题讨论】:

  • NSURLErrorBackgroundSessionRequiresSharedContainer(这就是-995 错误)让我怀疑后台服务不喜欢引用容器外部的内容。也许尝试将其复制到您的文档或临时文件夹,然后使用 uploadParametersWithFileURL 从那里使用 fileURL 上传。
  • FWIW,看起来这就是 Sergey 在他的回答中要去的地方......

标签: ios objective-c ios9 nsurlsession youtube-data-api


【解决方案1】:
  1. 考虑这一行:

    var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL!
    

    这会强制解包info[UIImagePickerControllerMediaURL](这很糟糕,因为如果是nil,应用程序会崩溃)并将其转换为隐式解包的可选NSURL!。那没有意义。只需进行有条件的展开(并展开为NSURL,而不是NSURL!):

    if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL { ... }
    
  2. 下一行调用filePathURL

    var videoFileURL = videoDataURL.filePathURL
    

    如果您想要一个文件 URL,您已经有了一个,因此无需转换,只需使用 videoDataURL。如果你真的想要一条路径,你会使用path 方法:

    let videoPath = videoDataURL.path
    

    坦率地说,Apple 正试图让我们不再使用字符串路径,所以只需使用原始的 videoDataURL 并避免同时使用路径和 filePathURL

  3. 你正在使用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 块中完成。

  4. 顺便说一句,正如您将在我上面的所有示例中看到的那样,应该尽可能使用let

坦率地说,我建议不要将其加载到 NSData 中。只需用NSFileManager 复制即可,这样可以更有效地使用内存。如果视频很长,它可能会很大,您应该避免在任何给定时间点将整个视频加载到内存中。

所以你可以:

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)
    }
}

如果您要将其上传到网络服务,则可以使用NSURLSessionUploadTask,使用文件或流选项。这个请求的构建是一个单独的问题,但希望您能明白:对于像照片或特别是视频这样的大型资产,如果可以避免的话,不要用资产实例化 NSData

【讨论】:

    【解决方案2】:

    如果您的手机中存在您的文件而不是 [NSURL URLWithString:videoURL],请尝试此操作。

    NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoURL]];

    【讨论】:

    • 我做了 fileData 返回 nil
    • 你能记录下videoURL吗?
    • 这是 videoURL file:///var/mobile/Media/DCIM/102APPLE/IMG_2187.MOV
    • 更新问题
    • 如果你使用你的代码 [NSURL URLWithString:videoURL],fileData 是 nil 吗?
    猜你喜欢
    • 2015-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多