iosswifturlsessiondispatchgroup

Call two API's and build structure - iOS - Swift


i know this is common but couldn't find answers. I thought of using dispatchGroups but not sure how I could do

Requirement: API 1 gives id, I need to construct url with that id and call another API to fetch imageUrl and then build struct with imageUrl

struct Item {
 let itemId: String?
 let quantity: String?
 let itemImageUrl: String?
}

struct InitialDetails: Codable {
  let id: String
  let quantity: String
}

struct ImagePathData: Codable {
 let imageUrl: String
}

API 1:

{ 
 items: [{
   id: "1",
   quantity: "10"
}]
}

API 2

{
itemImagePath: "https://itemizedUrl/fish.png"
}

Code

func fetchData() -> [Item] {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        var items: [Items] = []
        let initialData = try JSONDecoder().decode([InitialDetails].self, from: data)
        for info in initialData {
            var imageUrlPath: String?
            let imageDataUrl = "https://itemizedUrl.com/\(info.id)"
            URLSession.shared.dataTask(with: imageDataUrl) { (data, response, error) in
                imageUrlPath = try JSONDecoder().decode(ImagePathData.self, from data)
            }
            let item = Item(itemId: initialData.id,
                  quantity: initialData.quantity,
                  itemImageUrl: imageUrlPath)
            items.append(item)
        }
        return items
     }
}

I know this is not right..pls advice how I could achieve this scenario


Solution

  • You need a completion with a dispachGroup

    func fetchData(completion:@escaping([Item]) -> ()) { 
      var items: [Items] = []
      let g = DispatchGroup()
      URLSession.shared.dataTask(with: url) { (data, response, error) in
      do {
      let initialData = try JSONDecoder().decode([InitialDetails].self, from: data)
      for info in initialData {
       g.enter() 
       let imageDataUrl = "https://itemizedUrl.com/\(info.id)"
       URLSession.shared.dataTask(with: imageDataUrl) { (data, response, error) in
         do {
         let imageUrlPath = try JSONDecoder().decode(ImagePathData.self, from data)
             let item = Item(itemId: initialData.id,
                      quantity: initialData.quantity,
                      itemImageUrl: imageUrlPath.imageUrl)
            items.append(item)
            g.leave()
            } catch { 
             print(error)
            }
       } 
      }
      } catch  {  
         print(error)
      }
      g.notify(queue:.main) {
        completion(items)
      }
     }
    }