Sarge
Sarge

Reputation: 2366

Convert '[Publishers.Map<URLSession.DataTaskPublisher, [ProductRep]?>]' to [ProductRep]

How do I figure out the flatMap, reduce, etc. to turn this into an array of ProductRep?

I'm currently getting Cannot convert value of type 'Publishers.Map<URLSession.DataTaskPublisher, [StoreService.ProductRep]?>' to closure result type 'StoreService.ProductRep' - because I don't really understand how to turn a Publishers.Map into the actual thing. This is intended to be part of a larger network of publishers and subscribers using map/flatMap.

let mapResult: [ProductRep] = parsePageURIs(firstPage, jsonDict)
            .map { pageUri in self.importProductsPublisher(pageUri, urlSession: urlSession, firstPage: false) }
            .map { publisher in publisher.map {(productsData, productsResponse) in
                    return self.handleImportProductsResponse(data: productsData, response: productsResponse, category: category, urlSession: urlSession)
                }
        }
func importProductsPublisher(_ uri: String, urlSession: URLSession, firstPage: Bool) -> URLSession.DataTaskPublisher { /* Start the network query */ }
func handleImportProductsResponse(data: Data, response: URLResponse, category: CategoryRep, urlSession: URLSession) -> [ProductRep]? { /* Handle the result of the network query and parse into an array of items (ProductRep) */ }

Upvotes: 1

Views: 243

Answers (1)

Jason
Jason

Reputation: 797

I think there's 2 things going on here. Firstly, you are missing a sink of some kind, usually you'll see a chain of publishers end in something like .sink or .assign

whatever.map{ ... }.sink{ items in 
//Do something with items in this closure
}

Secondly is you appear to be mapping page uris to a collection of Publishers, rather than a single publisher. Then you have a nested map inside a map, which doesn't resolve anything yet.

You may be able to use one of the merge publishers, like merge many and collect to reduce from one publisher to many: https://developer.apple.com/documentation/combine/publishers/mergemany/3209693-collect

A basic collection example:


let arrayOfPublishers = (0...10).map{ int in
    return Just(int)
}

Publishers.MergeMany(arrayOfPublishers).collect().sink { allTheInts in
    //allTheInts is of type [Int]
    print(allTheInts)
}

I think you need something like this:


 let productPublishers = parsePageURIs(firstPage, jsonDict).map { pageUri in
    return self.importProductsPublisher(pageUri, urlSession: urlSession, firstPage: false).map {(productsData, productsResponse) in
        return self.handleImportProductsResponse(data: productsData, response: productsResponse, category: category, urlSession: urlSession)
    }
 }

 Publishers.MergeMany(productPublishers).collect().sink { products in
   //Do somethings with the array of products
 }

map the uris to publisher results in a Model after mapping a data request publisher, then merge all your publishers to take the individual results into one array with MergeMany & collect, and finally the sink which actually triggers everything to happen.

Upvotes: 1

Related Questions