【问题标题】:Async call in loop func. Return only when async finished循环函数中的异步调用。仅在异步完成时返回
【发布时间】:2016-12-08 10:43:12
【问题描述】:

我有一个 Alamofire 调用,我在其中获取项目列表,然后解析它们:

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

当我解析列表时,我需要再次调用以获取项目的状态:

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

主要问题是我需要在第一个函数中完成之前获得所有项目状态,现在当循环已经返回数组时我会得到一些状态响应。返回带有状态的解析列表的最佳解决方案是什么?

【问题讨论】:

  • 使用 dispatch group 和 dispatch_group_wait 调用completjon(list)

标签: ios swift3 closures alamofire


【解决方案1】:

将解析函数更改为闭包并添加 DispatchGroup 直到设置所有状态。

第一个函数:

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

第二个功能:

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

【讨论】:

    【解决方案2】:

    你可以使用一个简单的循环计数器来实现你想要的......

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

    从这里我修改了你的一些代码...我声明了一个计数器来确定何时抛出带有状态项的完整列表的回调。

    class func parseList(_ responseArray: NSArray, _ completion: @escaping (Array<Any>) -> Void) {
        let list = NSMutableArray()
        let counter: Int = 0 // counter
    
        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) // when the alamofire return the call we set the status then add it to our list..
                   counter += 1 // then increment our counter
    
                    // here ... we verify if the counter matches the total count of the item we need need to fetch
                    if responseArray.count == counter {
                        completion(list) // if it matches the total count then we will fire the callback with the list of the item with statuses.
                    }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-14
      • 1970-01-01
      • 1970-01-01
      • 2020-03-07
      • 2019-06-17
      • 1970-01-01
      • 2014-05-12
      相关资源
      最近更新 更多