【问题标题】:Get the data from NSURLSession DownloadTaskWithRequest from completion handler从完成处理程序中获取来自 NSURLSession DownloadTaskWithRequest 的数据
【发布时间】:2015-06-11 01:40:26
【问题描述】:

所以我很难理解一些事情。这是我对 NSURSession 的理解:

  • 一般来说,我有 2 个选项(据我所知)DataTask(ex dataTaskWithRequest)DownloadTask(ex DownloadTaskWithRequest) - 使用他们的委托方法,使用完成处理程序,不能两者都做。 我已经设法像这样使用 dataTaskWithRequest 接收数据:

    let request = NSMutableURLRequest(URL: dataSourceURL!)
    request.HTTPMethod = "POST"
    
    let postString = "lastid=\(id)"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in
    
        if error != nil {
            println("error=\(error)")
            return
        }
        if data != nil {
            println("works")
            //Handle data
    
    
        }
        //println("response = \(response)")
    
    
    }
    task.resume()      
    

完美运行。问题是我需要将数据 DOWNLOAD 到磁盘,而不仅仅是内存(我正在下载图像)。所以我对 DownloadTaskWithRequest +他的完成处理程序进行了同样的尝试,我注意到他采用的参数与第一个参数相同,即 NSURLDataTaskWithRequest NSData 所以它让事情变得非常简单。 例如。

 let task2 = NSURLSession.sharedSession().downloadTaskWithRequest(request, completionHandler: { (location : NSURL!, response : NSURLResponse!, error : NSError?) -> Void in
            if error != nil {
                return
            }

            //How do I get the data??
        })
task2.resume()

我的问题是这样的:我知道我可以使用以下方法从 Location(NSURL) 中获取数据:

    var data = NSData(contentsOfURL: location)

1) contentsOfURL 会发出另一个“请求”来获取这些数据,还是他在本地工作?如果它再次发送请求,我该如何避免它?

2)这是正确的方法吗(我知道我可以使用委托方法,但我不喜欢)?

3)我如何在本地存储我下载的数据(在回答第 1 和第 2 个问题后),并在需要时访问它?

谢谢你们!!对不起新手问题,我真的很关心效率 - 谢谢!

【问题讨论】:

    标签: ios swift nsdata nsurlsession nsurlsessiondownloadtask


    【解决方案1】:

    使用下载任务时,通常只需使用下载任务的completionHandler 提供的location 即可将文件从其临时位置移动到您选择的最终位置(例如到文档或缓存文件夹)使用NSFileManager

    let task = NSURLSession.sharedSession().downloadTaskWithURL(url) { location, response, error in
        guard location != nil && error == nil else {
            print(error)
            return
        }
    
        let fileManager = NSFileManager.defaultManager()
        let documents = try! fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
        let fileURL = documents.URLByAppendingPathComponent("test.jpg")
        do {
            try fileManager.moveItemAtURL(location!, toURL: fileURL)
        } catch {
            print(error)
        }
    }
    task.resume()
    

    您当然也可以使用contentsOfURL 将对象加载到NSData。是的,它适用于本地资源。而且,不,它不会发出另一个请求……如果您查看 URL,它是本地文件系统中的文件 URL。但是这样你会失去下载任务的大部分内存节省,所以如果你真的想将它放入NSData,你可以使用数据任务。但是,如果您想将其移至持久存储,上述模式可能是有意义的,完全避免使用 NSData 对象。

    【讨论】:

    • Rob,老实说,我愿意为您提供关于 NSURLSession 的所有知识:D,问题是为了更好的用户体验,我想在本地保存文件(仅限图像),所以如果用户退出并打开它再次它不会重新下载它。在效率方面,您能解释一下 Documents 或 Cache 文件夹之间的区别吗?我以后如何访问数据并将其加载到例如图像视图?谢谢!!
    • 文档与缓存文件夹无关紧要。有关文档与缓存的讨论,请参阅File System Basics(前者用于备份的用户文件;后者用于在设备存储空间不足时可以删除的资源,并且仅用于可以重新检索的资源)。关键是,如果您在下载任务中避免使用NSData,您将确保在应用程序运行时占用更少的内存。
    • 但是是否可以从文档目录加载带有文件的图像视图?你能举个例子吗?如果我理解正确,当我下载图像时,您将其保存为特定路径的文件?
    • 当然,你可以使用UIImage(contentsOfFile:)(或者如果使用NSURL,使用NSData(contentsOfURL:)和文件URL,然后UIImage(data:),然后加载UIImageViewimage属性)。
    • 不,您可以在此移动过程中重命名它。如果重命名失败并且您像我上面那样实现了它(我 println 错误),它应该打印一条错误消息。它打印了什么错误?顺便说一句,如果您将其放在子目录中,请务必先创建该子目录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多