iOS NSURLSession 使用自定义委托(delegate)处理数据任务的完成

标签 ios swift cocoa-touch ios8

我的最终目标是在后台发出 http 请求,同时在内存中处理响应。根据我的理解,后台请求必须使用自定义委托(delegate)(这意味着我不能使用 dataTaskWithRequest(request, completionHandler)),并且要处理内存中的响应我必须使用数据任务(这意味着我不能将下载任务与 URLSession(session, downloadTask, didFinishDownloadingToURL) 一起使用)。

根据这个:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html#//apple_ref/doc/uid/10000165i-CH2-SW1看起来没有任何委托(delegate)方法在完成时被调用以处理数据任务。通过委托(delegate)处理响应以通过 URLSession(session, dataTask, data) 处理单个 NSData 片段的唯一方法是什么? https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSessionDataDelegate_protocol/index.html#//apple_ref/occ/intfm/NSURLSessionDataDelegate/URLSession:dataTask:didReceiveData : 没有将整个最终响应作为单个 NSData 实例处理的委托(delegate)方法吗?

最佳答案

对于需要立即显示的 API 调用等少量数据或头像等小图像,dataTaskWithRequest(request, completionHandler) 是您需要的方法。它设置了一个异步任务,这意味着当您启动该任务时,执行将立即返回到您的代码,该任务将在您的应用程序运行时“在后台”负责下载数据并将其缓冲在内存中。一旦所有的下载任务完成,它会调用你的 completionHandler 让它知道它已经完成并且数据已经准备好了。它会将数据作为参数传递给您的处理程序。

对于较大的文件,如播客、视频和大图像,您会希望 iOS 为您下载文件,即使用户开始查看另一个应用程序并且您的应用程序已暂停。然后你会想要使用 NSURLSessionDownloadTask具有后台 session 配置 backgroundSessionConfigurationWithIdentifier: 和自定义委托(delegate)。您的自定义委托(delegate)将需要实现方法 URLSession:downloadTask:didFinishDownloadingToURL:。调用此方法时,您可以使用如下代码读取传递给您的 url 文件的内容:

let data = NSData(contentsOfURL: url)

这样处理 iOS 应用程序退出后后台下载持续存在的原因是 iOS 希望能够代表不同的应用程序(如播客、视频等)继续下载多个文件。如果用户处于高速状态速度网络,在内存中下载多个大文件会很快消耗所有设备内存,因此它们会在下载时存储起来。同样,在使用 NSData(contentsOfURL:) 将整个文件读入内存之前,您应该牢记文件大小。

这是一个工作示例,说明所有内容如何组合在一起。将此粘贴到 iOS playground 中并查看您将获得的图像:

import UIKit

class MyDelegate: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate {
  func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
    if let data = NSData(contentsOfURL: location) {
      // work with data ...
      UIImage(data: data)
    }
  }
}

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("my-session-identifier")
let delegate = MyDelegate()
let session = NSURLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
let url = NSURL(string: "https://pbs.twimg.com/profile_images/473550724433858560/tuHsaI2U.png")!
let task = session.downloadTaskWithURL(url)
task.resume()

// this allows the code to run in a playground
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

关于iOS NSURLSession 使用自定义委托(delegate)处理数据任务的完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34145271/

相关文章:

ios - UITextView 委托(delegate)多次调用

ios - UIView旋转文字操作

ios - 在 UIButton 上同时显示图像和标题 - Swift 3

objective-c - 离线生成二维码

cocoa-touch - 主要的 Grand Central Dispatch 队列是串行的还是并发的?

ios - Facebook 和键盘动画管理

ios - 更改 UIPickerView pickerView :viewForRow: attributes based on a certain condition

ios - 从 NSUserDefaults 解包 NSMutableArray

ios - 扩展 UIPickerView 以更改标题颜色

ios - 在 iOS 中获取当前设备语言?