通过从URL会话创建任务,将接收到的数据直接存储到缓存中
Overview
对于于远程服务器的小型交互,可以使用URLSessionDataTask类将相应数据接收到缓存中(与使用URLSessionDownLoadTask类相反,后者将数据直接存储到文件系统中)。数据任务非常适合诸如调用web服务器终结点之类的用途。
您使用URL会话实例创建任务。如果你的需求很简单,你可以使用URLSession共享实例。如果你想通过代理回调和转移来交互,则需要创建一个回话而不是共享实例。你使用URLSessionConfiguration实例创建会话,同时还要传入实现URLSessionDelegate或其子协议之一的类。可以重复使用会话来创建多个任务,因此对于所需的每个唯一配置请创建一个会话并将其存储为属性。
Note
注意不要创建过多的会话。例如您的应用有多个部分需要配置蕾丝的会话,创建一个并分享给他们。
拥有了一个回话后,你可以使用dataTask()方法之一创建任务。任务以挂起状态创建,可以通过调用resume()来启动。
Receive Results with a Completion Handler
提取数据最简单的方法是创建一个使用完成处理程序的任务。通过这种安排,任务会将服务器的响应,数据和可能的错误传递到你提供的完成处理程序块。图一展示了会话和任务之间的关系,以及如何将结果传递到完成处理程序块。
image.png
要创建使用完成处理程序的数据任务,请调用URLSession的dataTask(with :)方法。您的完成处理程序需要做三件事:
- 验证错误参数为nil,如果不是,则发生了传输错误,处理错误并退出
- 检查响应参数来验证状态码是否指示成功,MIME类型是否是期望的值。如果不是,处理服务器错误并退出。
- 根据需要使用数据实例
清单1显示了用于获取URL内容的startLoad()方法。首先使用URLSession类的共享实例来创建一个数据任务,该任务将其结果传递给完成程序块。检查本地和服务器错误后,此处理程序将数据转换为字符串,并使用其填充WKWebView出口。当然,您的应用程序可能还有其他用途来获取数据,例如将其解析为数据模型。
表单一创建了一个完成处理程序,以接收数据加载结果
func startLoad() {
let url = URL(string: "https://www.example.com/")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
self.handleClientError(error)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
self.handleServerError(response)
return
}
if let mimeType = httpResponse.mimeType, mimeType == "text/html",
let data = data,
let string = String(data: data, encoding: .utf8) {
DispatchQueue.main.async {
self.webView.loadHTMLString(string, baseURL: url)
}
}
}
task.resume()
}
Import
在与创建任务的队列不同的Grand Central Dispatch队列上调用完成处理程序。因此,任何使用数据或错误来更新UI的工作(例如更新webView)都应明确放置在主队列中,如下所示。
Receive Transfer Details and Results with a Delegate
为了在执行任务时获得更高级别的访问权限,在创建数据任务时,您可以在绘画上设置委托,而不是提供完成处理程序。图2显示了这种安排。
图2实现了代理来接收任务返回的结果
image.png
通过这种方式,部分数据在到达时会提供给URLSessionDataDelegate 的urlSession(_:dataTask:didReceive:)方法,直到传输完成或者失败并出现导致。随着专一的进行,委托还会接受其他类型的事件。
在使用委托方式的时候,你需要创建你自己的URLSession实例,而不是使用URLSession类的简单共享实例。创建一个新会话可以让您将自己的类设置为会话的委托,如清单2所示。
声明你的类,实现一个或多个委托协议(URLSessionDelegate,URLSessionTaskDelegate,RULSessionDataDelegate,and URLSessionDownloadDelegate).然后使用初始化init(configurationLdelegateLdelegateQueue:)创建URL会话实例。您可以自定义与此初始化程序一起使用的配置实例。例如最好将waitsForConnectivity设置为true,这样,会话将等待适当的连接,而不是在所需的连接不可用时立即失败。
private lazy var session: URLSession = {
let configuration = URLSessionCOnfiguration.default
configuration.waitsForConnectivity = true
return URLSession(configuratio: configuration, delegate: self. delegateQueue:nil)
}
清单3显示了一个startLoad()方法,该方法使用此会话来启动数据任务,使用委托回调处理接收到的数据和错误。这个表单实现了三个代理回调:
- urlSession(_:dataTask:didReceive:completionHandler:)验证响应是否具有成功的HTTP状态代码,并且MIME类型为text / html或text / plain。如果不是上述两者结果之一,任务被取消,否则,他可以继续执行。
- urlSession(_:dataTask:didReceive :)接收任务接收到的每个Data实例,并将其附加到一个称为ReceivedData的缓冲区中。
- urlSession(_:task:didcCompleteWIthError:)首先查看是否发生了传输级错误,如果没有错误,他将尝试将ReceiveData缓冲区转换为字符串并将其设置为webView的内容。
表单3 使用了URL sessiondatatask的委托
var receivedData: Data?
func startLoad() {
loadButton.isEnabled = false
let url = URL(string: "https://www.example.com/")!
receivedData = Data()
let task = session.dataTask(with: url)
task.resume()
}
// delegate methods
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse,
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
guard let response = response as? HTTPURLResponse,
(200...299).contains(response.statusCode),
let mimeType = response.mimeType,
mimeType == "text/html" else {
completionHandler(.cancel)
return
}
completionHandler(.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.receivedData?.append(data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
DispatchQueue.main.async {
self.loadButton.isEnabled = true
if let error = error {
handleClientError(error)
} else if let receivedData = self.receivedData,
let string = String(data: receivedData, encoding: .utf8) {
self.webView.loadHTMLString(string, baseURL: task.currentRequest?.url)
}
}
}
各种委托协议提供了以上代码中所示方法之外的方法,用于处理身份验证挑战,重定向之后和其他特殊情况,在URLSession讨论中,使用URL会话描述了在传输过程中可能发生的各种回调。
网友评论