0

I've got a generic "perform" method to download some data from the network (Some code omitted):

   func perform<D: Decodable>(_ endPoint: EndPoint) -> AnyPublisher<D, APIProviderError> {
      do {
         let request = try requestBuilder.build(with: endPoint)

         return try configurateSession(urlRequest: request, stub: endPoint.testData)
            .dataTaskPublisher(for: request)
            .decode(type: D.self, decoder: JSONDecoder())
      catch {
            fatalError(error.localizedDescription)
      }
}

  1. Initially I load the main page structure. json example:
{
   "layout": {
      "id": "10",
      "slots": [
         {
            "slotNumber": 1,
            "widgets": [
               {
                  "id":"10",
                  "type": "booking"
               },
               {
                  "id": "11",
                    "type": "banners"
               },
               {
                  "id":"12",
                  "type": "chips"
               },
               {
                  "id":"13",
                  "type": "products"
               },
               {
                  "id": "15",
                    "type": "banners"
               }
   ]
}

and parse it into an array of structures

struct Container: Decodable {
   let layout: Layout
}

struct Layout: Decodable {
   let slots: [Slot]
}

struct Slot: Decodable {
   let widgets: [Section]
}

struct Section: Decodable  {
   private enum CodingKeys: String, CodingKey {
      case id, type
   }

   let id: String
   let type: SectionType
   var items: [Item]?
}

enum SectionType: String, Decodable {
   case banners, brands, products, orders, coupons, map, card, booking, chips
}
  1. For each widget(Section), depending on its type, I need to load its items and mutate widget. Item examples:

{
   "data": [
      {
         "offerPrice": "59.99",
         "name": "ss",
         "id": "60461"
      },
      {
         "offerPrice": "79.99",
         "name": "www",
         "id": "60750"
      }]
}

{
   "data": [
      {
         "image": "url"
      },
      {
         "image": "url",
         "categoryId": "3074457345616766223"
      }
      ]
   }

to

struct ItemContainer<T: Decodable>: Decodable {
   let id: String
   let items: [T]
}

class Banner: Item, Decodable {
   let categoryID: String?
   let infoID: String?
   let imageURL: String?
}

class Product: Item, Decodable {
   let id: String
   let name: String
   let offerPrice: String
}

I think For each widget it is necessary to create a publisher. I don't understand what to do next. Zip does not work with collections

I wrote the following:

      provider.perform(.structMain)
         .map { (container: Container) in
            container.layout.slots.first?.widgets
         }.eraseToAnyPublisher()
         .sink(receiveCompletion: { _ in

         }, receiveValue: { result in
          ????????
         })
         .store(in: &self.cancellableset)

Or do I need something else

  • 1
    I feel like there are multiple concepts here, and it's not immediately clear where the problem is. First, your `Widget` model doesn't map to the JSON you showed, so you must be doing manual decoding. Have you already decoded it correctly - i.e. do you have an array of `Widget` or a single `Widget` with items? It's unclear to me what you have/need. Do you need to make a second request to update the data? Which data? What is `provider.perform`? – New Dev Jul 22 '20 at 13:04
  • @NewDev Thank you for the answer! I updated some code , please check it. I have an array of widgets where each widget has an additional array of elements. I need to fill all the widgets with additional information from the server and display this in the collection view. Each widget is a section – Christian Moler Jul 22 '20 at 15:35
  • 1
    If you want to do this in one publisher chain, see if this answer helps: https://stackoverflow.com/a/61968621/968155 – New Dev Jul 22 '20 at 15:53
  • Thank you! Seems that what I need – Christian Moler Jul 22 '20 at 16:33

0 Answers0