Правильная обработка делегатов сеанса

Я хочу убедиться, что правильно реализую 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. Должен ли я всегда выполнять завершениеHandler в ответе didReceive, и он всегда должен быть .allow? Может быть, мне следует делать это только в том случае, если код состояния ответа равен 200?
  2. Является ли код состояния 200 единственным, что мне действительно нужно проверить в этом случае, и это правильное место для инициализации данных? Может быть, эта функция может выполняться несколько раз с разными кодами, и я должен относиться к каждому коду по-разному?
  3. Является ли didCompleteWithError единственным местом, где мне нужно указать ошибку? Может быть, ошибки тоже могут генерироваться в разных местах?
  4. В документации для URLResponse я вижу значение по умолчанию для ожидаемогоContentLength — NSURLResponseUnknownLength, но это значение не существует. Есть ли какое-то новое название для него сейчас?
  5. Есть ли что-то еще, что я должен знать, чтобы этот код был универсальным?

person Damian Dudycz    schedule 12.11.2016    source источник


Ответы (1)


  1. Если код статуса не равен 200, часто тело ответ включает информацию, которая поможет вам диагностировать, почему это не 200, поэтому вы, вероятно, захотите продолжить сбор этой информации. Я бы, наверное, переместил проверку кода состояния на didCompleteWithError.

  2. Обычно я ожидаю 200 и поэтому проверяю только 200. Технически все коды 2xx являются кодами «успешного завершения», поэтому вы можете считать их все успешными. Это зависит от вас.

  3. didCompleteWithError - единственная ошибка, связанная с подключением. Теоретически вы можете проверить urlSession(_:didBecomeInvalidWithError:). Кроме того, вы можете захотеть назначить свой собственный код ошибки, если вы получаете код состояния, отличный от 2xx, или, на более высоком уровне, если синтаксический анализ ответа не удался.

  4. Похоже, что они не определили подходящую константу из Swift 3. К вашему сведению, глядя на заголовки, вы можете увидеть значение -1, но часто мы просто проверяем response.expectedContentLength < 0.

person Rob    schedule 12.11.2016
comment
Спасибо за объяснение. Поэтому я всегда создаю data = Data() в ответе didReceive и буду проверять коды состояния после didCompleteWithError. - person Damian Dudycz; 12.11.2016