9

I'm using a dataTaskPublisher to fetch some data:

func downloadData(_ req: URLRequest) {
  self.cancelToken = dataTaskPublisher(for: req).sink { /* ... */ }
}

If the function is called while the request is in progress, I would like to return.

Currently I either:
1. Set the cancelToken to nil in the sink or
2. Crate and manage a isDownloading variable.

Is there a built-in way to check if the dataTaskPublisher is running (and optionally its progress)?

Asperi
  • 228,894
  • 20
  • 464
  • 690
chustar
  • 12,225
  • 24
  • 81
  • 119

2 Answers2

8

I mostly agree with @Rob, however you can control state of DataTask initiated by DataTaskPublisher and its progress by using of URLSession methods:

func downloadData(_ req: URLRequest) {
    URLSession.shared.getAllTasks { (tasks) in
        let task = tasks.first(where: { (task) -> Bool in
            return task.originalRequest?.url == req.url
        })

        switch task {
        case .some(let task) where task.state == .running:
            print("progress:", Double(task.countOfBytesReceived) / Double(task.countOfBytesExpectedToReceive))
            return
        default:
            self.cancelToken = URLSession.shared.dataTaskPublisher(for: req).sink { /* ... */ }
        }
    }
}
Denis Kreshikhin
  • 8,856
  • 9
  • 52
  • 84
  • Can someone maybe explain how this works and where you would call this in order to get regular updates to the progress? – Björn Oct 03 '21 at 11:05
  • @Björn You can find a task by url and then check task.countOfBytesReceived and task.countOfBytesExpectedToReceive for getting of the progress. For regular updates you should use a timer. – Denis Kreshikhin Oct 04 '21 at 18:12
6

Regarding getting progress from this publisher, looking at the source code, we can see that it’s just doing a completion-block-based data task (i.e. dataTask(with:completionHandler:)). But the resulting URLSessionTask is a private property of the private Subscription used by DataTaskPublisher. Bottom line, this publisher doesn’t provide any mechanism to monitor progress of the underlying task.

As Denis pointed out, you are limited to querying the URLSession for information about its tasks.

Rob
  • 415,655
  • 72
  • 787
  • 1,044