Combine, recupere una matriz de imágenes de una matriz de URL y asígnelas al objeto correspondiente

Soy bastante nuevo en el uso de Combine y, francamente, no sé si esta pregunta es tonta o no. De todos modos, tengo un editor que luego devuelvo a la persona que llama con una serie de objetos recuperados de una operación RESTful de la siguiente manera:

       let publisher = URLSession.shared.dataTaskPublisher(for: URL)
        .handleEvents(
            receiveSubscription: { _ in
                activityIndicatorPublisher.send(true)
            }, receiveCompletion: { _ in
                activityIndicatorPublisher.send(false)
            }, receiveCancel: {
                activityIndicatorPublisher.send(false)
            })
        .tryMap { data, response -> Data in
            guard let httpResponse = response as? HTTPURLResponse,
                  httpResponse.statusCode == 200 else {
                      throw NetworkError.httpError
                  }
            print(String(data: data, encoding: .utf8) ?? "")
            return data
        }
        .decode(type: [ShowElement].self, decoder: JSONDecoder())
        .flatMap { $0.publisher }
        .map(\.show?.image?.medium)
        .flatMap(maxPublishers:.max(1)) { url in
            URLSession.shared.dataTaskPublisher(for: url)
                .map(\.data)
                .replaceError(with: Data())
        }
        .map{ imageData, item -> ShowElement in
            var mutableItem = item
            mutableItem.imageData = imageData
            return mutableItem
        }
        .collect()
        .catch { error -> Just<[ShowElement]> in
            print(error)
            return Just([])
        }
        .eraseToAnyPublisher()
    return publisher
}

Cuando hago dataTaskPublisher recibo el error: "No hay coincidencia exacta en la llamada al método de instancia dataTaskPublisher, y cuando hago el mapeo de imageData recibo otro error:" Tipo de cierre contextual '(Publishers.FlatMap<Publishers.SetFailureType<Publishers .ReplaceError<Publishers.MapKeyPath<URLSession.DataTaskPublisher, Data>>, Error>, Publishers.MapKeyPath<Publishers.FlatMap<Publishers.SetFailureType<Publishers.Sequence<[ShowElement], Never>, Error>, Publishers.Decode<Publishers. TryMap<Publishers.HandleEvents<URLSession.DataTaskPublisher>, JSONDecoder.Input>, [ShowElement], JSONDecoder>>, String?>>.Output) -> ShowElement' (también conocido como '(Data) -> ShowElement') espera 1 argumento, pero se usaron 2 en cuerpo de cierre"

Answer

Cada matriz se puede utilizar como editor.

Supongamos que showArrayrepresenta el [ShowElement]objeto.

Solo llama publisher

showArray.publisher

luego asigne cada elemento a su URL

.map(\.url) // replace `url` with the real property name

luego flatMapla URL para cargar cada imagen secuencialmente

.flatMap(maxPublishers:.max(1)) { url in
            URLSession.shared.dataTaskPublisher(for: url)
               .map(\.data)
               .replaceError(with: Data())
}

luego zipel resultado con el ShowElementítem correspondiente

.zip(showArray.publisher)
  

luego asigne el resultado y asigne el valor

.map{ (imageData, item) -> ShowElement in
       var mutableItem = item
       if let image = UIImage(data: imageData) {
          mutableItem.image = image // replace `image` with the real property name
       }
       return mutableItem
}

Finalmente collectlos elementos

.collect()

El resultado es una matriz de ShowElementincluir las imágenes.