正确处理会话委托

Correct handling session delegates

我想确保以正确的方式实施 URLSessionTaskDelegate 和 URLSessionDataDelegate。我使用它们,因为我希望能够跟踪进度。这是到目前为止的代码:

final public fileprivate(set) var data:     Data?
final public fileprivate(set) var response: URLResponse?
final public fileprivate(set) var error:    Error?


public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {        
    if let response = response as? HTTPURLResponse, response.statusCode == 200 {
        data = Data()
    }

    self.response = response

    completionHandler(.allow)
}

public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
    self.data?.append(data)
}

public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
    self.error = error

    // ... Work with downloaded data
}

还有几个问题:

  1. 我是否应该始终在 didReceive 响应中执行 completionHandler,并且应该始终是 .allow?也许我应该只在响应状态代码为 200 时才执行此操作?
  2. 在这种情况下,状态代码 200 是我真正需要检查的唯一代码吗?这是初始化数据的正确位置吗?也许这个函数可以用不同的代码执行几次,我应该区别对待任何代码?
  3. didCompleteWithError 是我唯一需要分配错误的地方吗?也许错误也可以在不同的地方产生?
  4. 在 URLResponse 的文档中,我可以看到 expectedContentLength 的默认值是 NSURLResponseUnknownLength,但这个值并不存在。现在有新名字吗?
  5. 为了使此代码通用,我还应该知道什么吗?
  1. 如果 status code 不是 200,通常响应的 body 包含帮助您诊断它不是 200 的原因的信息,因此您可能想继续捕获该信息。我可能会将该状态代码检查移动到 didCompleteWithError.

  2. 我通常期望 200,因此只检查 200。从技术上讲,所有 2xx 代码都是 "success" 代码,因此您可能希望将它们全部视为成功。由你决定。

  3. didCompleteWithError 是唯一与连接相关的错误。理论上,您可能想要检查 urlSession(_:didBecomeInvalidWithError:)。此外,如果您获得非 2xx 状态代码,或者在更高级别上,如果响应解析失败,您可能想要分配自己的错误代码。

  4. 他们似乎没有从 Swift 3 中定义适当的常量。仅供参考,查看 headers,您可以看到值为 -1, 但通常我们只检查 response.expectedContentLength < 0.