Обновление пользовательского интерфейса не работает для urlSession downloadTask didWriteData

В настоящее время у меня возникла проблема с обновлением пользовательского интерфейса при использовании задачи загрузки. Следующая функция должна обновлять пользовательский интерфейс, но она работает только иногда. Почему это не работает каждый раз, когда я загружаю файл? Журнал NSLog показывается в отладчике каждый раз!

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
  let curDownloadSize = totalBytesWritten / (1024*1024)
  let totalDownloadSize = totalBytesExpectedToWrite / (1024*1024)

  if curDownloadSize != oldDownloadSize {
    DispatchQueue.main.async {
      self.progressLabel!.text = "\(self.curDownloadSize)MB / \(self.totalDownloadSize)MB"
      self.progressView!.progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
      NSLog("Download progress: \(Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))");
    }
  }
}

В настоящее время доступны progressLabel и progressView.

Кстати, я тестировал его с одним и тем же файлом несколько раз, и иногда это работает, иногда нет.

Обновление: я читал об использовании второй очереди отправки, подобной этой.

DispatchQueue.global(qos: .utility).async {
  DispatchQueue.main.async {
    (same as above)
  }
}

но это также работает только иногда.


person who9vy    schedule 29.10.2017    source источник
comment
Вам вообще не нужно использовать DispatchQueue внутри этого метода.   -  person Leo Dabus    schedule 29.10.2017
comment
Хорошо, я пробовал это раньше с тем же результатом, за исключением того, что я считаю, что это не работает так часто, как с DispatchQueue.   -  person who9vy    schedule 29.10.2017
comment
вы делаете несколько загрузок одновременно? У вас только одна метка. Убедитесь, что вы отменили любую предыдущую задачу сеанса, прежде чем начинать новую.   -  person Leo Dabus    schedule 29.10.2017
comment
Опять же, этот метод уже вызывается/выполняется в основном потоке. Не используйте отправку там   -  person Leo Dabus    schedule 29.10.2017
comment
Нет множественных загрузок. И опять же, тоже без отправки, та же проблема.   -  person who9vy    schedule 29.10.2017


Ответы (1)


Недавно решил проблему.

Проблема возникает, если в основную очередь помещается слишком много событий. Это произошло только при очень хорошем интернет-соединении. В этом случае обратный вызов вызывался слишком часто.

Мое решение:

progressCounter += 1
if progressCounter % 30 == 0 {
  DispatchQueue.main.async {
    self.progressLabel!.text = "\(self.curDownloadSize)MB / \(self.totalDownloadSize)MB"
    self.progressView!.progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
    NSLog("Download progress: \(Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))");
  }
}

progressCounter был инициализирован до 0 ранее.

person who9vy    schedule 05.11.2017