Search code examples
iosswift3closuresalamofire

Async call in loop func. Return only when async finished


I have an Alamofire call where I get a list of items and then I parse them:

class func getList(_ completion:@escaping (Array<Item>) -> Void) {
    Alamofire.request("http://foo.com", method: .get, parameters: nil, headers: nil)
       .responseJSON { response in
           let list = parseList(response as! NSArray)
           completion(list)
    }
}

When I parse the list I need to make another call to get status of the item:

class func parseList(_ responseArray: NSArray) -> Array<Item> {
    let list = NSMutableArray()
    for itemDic in responseArray {
        let item  = Item()
        item.id   = itemDic.value(forKey: "Id") as? Int
        item.name = itemDic.value(forKey: "Name") as? Int

        Alamofire.request("http://bar.com", method: .get, parameters: nil, headers: nil)
           .responseJSON { response in
               item.status = response as? String
        }
        list.add(item)
    }
    return list as NSArray as! Array<Item>
}

The main issue is that I need to have all the items statuses before completion in the first func and now I get some status responses when the loop is already returned the Array. What is the best solution to return parsed list with statuses?


Solution

  • Change parse func to closure and add DispatchGroup till all statuses are set.

    First func:

    class func getList(_ completion:@escaping (Array<Item>) -> Void) {
        Alamofire.request("http://foo.com", method: .get, parameters: nil, headers: nil)
           .responseJSON { response in
               self.parseList(response as! NSArray, completion: { (list) in
                   completion(list)
               })
        }
    }
    

    Second func:

    class func parseList(_ responseArray: NSArray, completion:@escaping(Array<Item>) - Void) {
        let dispatch = DispatchGroup()
        let list     = NSMutableArray()
        for itemDic in responseArray {
            let item  = Item()
            item.id   = itemDic.value(forKey: "Id") as? Int
            item.name = itemDic.value(forKey: "Name") as? Int
            dispatch.enter()
            Alamofire.request("http://bar.com", method: .get, parameters: nil, headers: nil)
               .responseJSON { response in
                   item.status = response as? String
                   dispatch.leave()
            }
            list.add(item)
        }
        dispatchGroup.notify(queue: DispatchQueue.main) {
            completion(list as NSArray as! Array<Item>)
        }
    }