-1

I am quite new using Combine and frankly I don't know whether this question is silly or not, anyway I have a publisher which I then return to the caller with an array of objects retrieved from a RESTful operation in the following way:

       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
}

When I do the dataTaskPublisher I receive the error: "No exact match in call to instance methode dataTaskPublisher, and when I do the mapping of the imageData I receive another error: "Contextual closure type '(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' (aka '(Data) -> ShowElement') expects 1 argument, but 2 were used in closure body"

0

1 Answer 1

3

Every array can be used as a publisher.

Let's assume that showArray represents the [ShowElement] object.

Just call publisher

showArray.publisher

then map each item to its URL

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

then flatMap the URL to load each image sequentially

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

then zip the result with the corresponding ShowElement item

.zip(showArray.publisher)
  

then map the result and assign the value

.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
}

Finally collect the items

.collect()

The result is an array of ShowElement including the images.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi @vadian, thank you for your answer, I am sure it is perfect, but I am finding hard to understand where to start putting your lines of code into mine. If I put them at the end I receive the error that 'Value of type '[ShowElement]' has not my property, because it is taking it as an array, i's not going into the single element of the array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.