URLSession.shared.dataTask vs dataTaskPublisher, quando usar qual?

Oct 23 2020

Recentemente, encontrei duas APIs de busca de dados (download) que executam aparentemente a mesma coisa para mim. Não consigo ver quando devo usar um em vez do outro.

Eu posso usar 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()
        }
    }

Ou posso usar 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()
        }
    }

Não vejo suas diferenças distintas, já que ambos também podem buscar, e ambos também nos fornecem a capacidade de cancelar as tarefas facilmente. Alguém pode lançar alguma luz sobre suas diferenças em termos de quando usar qual?

Respostas

5 Eimantas Oct 23 2020 at 12:42

O primeiro é o clássico. Já está presente há algum tempo e a maioria, senão todos os desenvolvedores, está familiarizado com ele.

O segundo é um wrapper em torno do primeiro e permite combiná-lo com outros editores (por exemplo, Executar alguma solicitação apenas quando as duas primeiras solicitações forem realizadas). A combinação de tarefas de dados usando a primeira abordagem seria muito mais difícil.

Portanto, em resumo: use um primeiro para solicitações únicas. Use o segundo quando mais lógica for necessária para combinar / passar resultados com / para outros editores (não apenas de URLSession). Esta é, basicamente, a ideia por trás do framework Combine - você pode combinar diferentes formas de mecanismos assíncronos (datatasks que utilizam callbacks são um deles).

Mais informações podem ser encontradas no vídeo WWDC do ano passado sobre a introdução de colheitadeiras.