如何在Swift4

时间:2018-05-03 07:47:53

标签: ios swift multithreading closures swift4

 func getAll(completion: (([Foods]?, Error?) -> Void)?){      
        var foodWithEname: [Foods]?
        let food: Food? = Food()
        var sortedFood: [Foods]?
        food?.getFoods(){ (foodsArray, error) in
            sortedFood = foodsArray?.sorted{ (left, right) in   
                if let lh = left.hits  {  
                    if let rh = right.hits {
                        return left.hits! > right.hits!
                    }
                    return true
                } else {
                    if let rh = right.hits {
                        return false
                    }
                    return false
                }
            }


            for fa in foodsArray! {

                var f = Foods(fid: fa.fid, fname: fa.fname, hits: fa.hits, addr: fa.addr, ename: nil)

                food?.getEffectsById(fa.fid){ (effectsArray, error) in
                    //foodWithEname?.ename = effectsArray
                    print ("11111")

                    DispatchQueue.global().async {
                        f.ename = effectsArray
                        print ("2222")
                        foodWithEname?.append(f)
                    }
                }

                DispatchQueue.global().async (execute: {
                    print ("00000")

                })

            }
            print("3333")
            completion?(foodWithEname, nil)
        }
        print ("4444")
    }

我需要将foodWithEname Value返回到主视图,但是因为线程流而没有返回值...

我不知道如何控制闭合流程。

我在MainView中调用了该函数:

let food: Food? = Food()
food?.getAll(){ (foodsArray, error) in

        }

结果: 4444 3333 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222 11111 2222

我想要如下结果:

  

2222 00000 11111 2222 00000 11111 2222 00000 ... 3333

当完成时,Array值应该在foodWithEname中?(foodWithEname,nil)被执行。

请帮忙解决这个问题,谢谢!

2 个答案:

答案 0 :(得分:1)

您需要DispatchGroup来处理许多异步调用

func getAll(completion: (([Foods]?, Error?) -> Void)?){      
    var foodWithEname: [Foods]?
    let food: Food? = Food()
    var sortedFood: [Foods]?
    food?.getFoods(){ (foodsArray, error) in
        sortedFood = foodsArray?.sorted{ (left, right) in   
            if let lh = left.hits  {  
                if let rh = right.hits {
                    return left.hits! > right.hits!
                }
                return true
            } else {
                if let rh = right.hits {
                    return false
                }
                return false
            }
        }

      let dispatchGroup = DispatchGroup()

      for fa in foodsArray! {

            var f = Foods(fid: fa.fid, fname: fa.fname, hits: fa.hits, addr: fa.addr, ename: nil)

            dispatchGroup.enter()

            food?.getEffectsById(fa.fid){ (effectsArray, error) in

             f.ename = effectsArray

             foodWithEname?.append(f)

             dispatchGroup.leave()

            }


        }

        dispatchGroup.notify(queue: .main) {

             completion?(foodWithEname, nil)
        }


   }
 }

答案 1 :(得分:1)

在你的第二个循环中,你在循环中发送多个异步调用,而在结果等待时你调用了完成处理程序,结果是空的。

您需要在调度组中调用这些异步调用,并在完成所有执行后将结果返回到完成处理程序。

在第二个循环中执行类似的操作:

// Create dispatch group
let group = DispatchGroup()

for fa in foodsArray! {

    var f = Foods(fid: fa.fid, fname: fa.fname, hits: fa.hits, addr: fa.addr, ename: nil)

    // Enter in group just before the call
    group.enter()

    food?.getEffectsById(fa.fid){ (effectsArray, error) in
        //foodWithEname?.ename = effectsArray
        print ("11111")

        DispatchQueue.global().async {
            f.ename = effectsArray
            print ("2222")

            // Leave the group when task is completed
            group.leave()

            foodWithEname?.append(f)
        }
    }

    DispatchQueue.global().async (execute: {
        print ("00000")

    })
}
print("3333")

// Wait for all tasks to complete, and call the completion handler
group.notify(queue: DispatchQueue.main) {
    completion?(foodWithEname, nil)
}