URLSession.shared.dataTask vs dataTaskPublisher, when to use which?

Viewed 1302

I recently encounter two data fetching (download) API that performs seemingly the same thing to me. I cannot see when should I use one over the other.

I can use URLSession.shared.dataTask

    var tasks: [URLSessionDataTask] = []

    func loadItems(tuple : (name : String, imageURL : URL)) {
        let task = URLSession.shared.dataTask(with: tuple.imageURL, completionHandler :
        { data, response, error in
            guard let data = data, error == nil else { return }
            DispatchQueue.main.async() { [weak self] in
                self?.displayFlag(data: data, title: tuple.name)
            }
        })
        tasks.append(task)
        task.resume()
    }

    deinit {
        tasks.forEach {
            $0.cancel()
        }
    }

Or I can use URLSession.shared.dataTaskPublisher

    var cancellables: [AnyCancellable] = []

    func loadItems(tuple : (name : String, imageURL : URL)) {
        URLSession.shared.dataTaskPublisher(for: tuple.imageURL)
            .sink(
                receiveCompletion: {
                    completion in
                    switch completion {
                    case .finished:
                        break
                    case .failure( _):
                        return
                    }},
                receiveValue: { data, _ in DispatchQueue.main.async { [weak self] in self?.displayFlag(data: data, title: tuple.name) } })
            .store(in: &cancellables)
    }

    deinit {
        cancellables.forEach {
            $0.cancel()
        }
    }

I don't see their distinct differences, as both also can fetch, and both also provide us the ability to cancel the tasks easily. Can someone shed some light on their differences in terms of when to use which?

1 Answers

The first one is the classic. It has been present for quite some time now and most if not all developers are familiar with it.

The second is a wrapper around the first one and allows combining it with other publishers (e.g. Perform some request only when first two requests were performed). Combination of data tasks using the first approach would be far more difficult.

So in a gist: use first one for one-shot requests. Use second one when more logic is needed to combine/pass results with/to other publishers (not only from URLSession). This is, basically, the idea behind Combine framework - you can combine different ways of async mechanisms (datatasks utilising callbacks being one of them).

More info can be found in last year's WWDC video on introducing combine.

Related