10

我正在尝试为数组中的每个元素协调多个完成处理程序。

代码本质上是这样的:

var results = [String:Int]()

func requestData(for identifiers: [String])
{
    identifiers.forEach
    {   identifier in

        service.request(identifier, completion: { (result) in
            result[identifier] = result
        })
    }

    // Execute after all the completion handlers finish
    print(result)
}

因此,Array 中的每个元素都通过带有完成处理程序的服务发送,并且所有结果都存储在一个数组中。一旦所有这些处理程序完成,我希望执行一些代码。

我试图用DispatchQueue

var results = [String:Int]()

func requestData(for identifiers: [String])
{
    let queue = DispatchQueue.init(label: "queue")

    identifiers.forEach
    {   identifier in

        service.request(identifier, completion: { (result) in
            queue.sync
            {
                result[identifier] = result
            }
        })
    }

    // Execute after all the completion handlers finish
    queue.sync
    {
        print(result)
    }
}

但是 print 调用仍然是先执行的,有一个空的Dictionary

4

2 回答 2

31

如果我了解您要正确执行的操作,您可能想使用DispatchGroup

这是一个例子:

let group = DispatchGroup()

var letters = ["a", "b", "c"]

for letter in letters {
    group.enter()
    Server.doSomething(completion: { [weak self] (result) in
        print("Letter is: \(letter)")
        group.leave()
    })
}

group.notify(queue: .main) {
    print("- done")
}

这将打印如下内容:

b
c
a
// ^ in some order
- done
于 2017-11-20T05:00:13.530 回答
0

首先,请注意您service.request(...)是在异步模式下处理的。另一个问题是您想要完成该循环中的所有服务请求。

我的建议是使用完成处理程序创建函数,并在完成的每个循环上添加一个计数器。您的功能将与以下类似。

var results = [String:Int]()

func requestData(for identifiers: [String], callback:@escaping (Bool) -> Void)
{
    var counter = 0
    var maxItem = identifiers.count

    identifiers.forEach
    {   identifier in

        service.request(identifier, completion: { (result) in
            result[identifier] = result
            counter += 1
            if counter == maxItem {
                callback(true) // update completion handler to say all loops request are done
            }
            // if not, continue the other request
        })
    }
}

这就是代码的另一部分将调用函数并等待回调的方式

requestData(for identifiers:yourArrays) { (complete) in

    if complete {
        print(results)
    }
}

如果发生错误,不要忘记管理。

于 2017-11-20T05:05:44.310 回答