анализировать вложенные обработчики завершения

Я пытаюсь использовать обработчик завершения в цикле for. Проблема в том, что он будет продолжать выполнять цикл до возврата обработчика завершения, поскольку это асинхронный вызов. Прилагается мой код. Нужно ли использовать GCD? Я новичок (очевидно) в swift/ios. Любые советы будут высоко ценится. Боб

    for srcTerm in sFields {  //search using all search fields

        multiQuery (searchTerm: srcTerm)   {

            if srResult.count < self.lastValue {
                self.lastValue = srResult.count
                self.lastSearch = srcTerm
            }
        }
        // Do more stuff
    }


    func multiQuery (searchTerm: String,  completion: @escaping ([PFObject]) -> ()) {

        var exArray = [PFObject] ()
        let query = PFQuery(className: "searchLinks")

        do {

            query.whereKey("searchTerms", equalTo: searchTerm)

            query.findObjectsInBackground  (block: { (objects, error)-> Void in
                if let error = error {
                    print("Error Generated:  ",error)
                    return
                }
                if let objects = objects {
                   // do stuff
                }
                completion(self.srResult)
            })
        }
    }               // end of function

person Robert Marlan    schedule 30.08.2017    source источник
comment
Есть несколько способов сделать это (Dispatch Groups, promises и т.д.). Взгляните на stackoverflow.com/a/23112134/2124535.   -  person nathan    schedule 30.08.2017
comment
Возможный дубликат GCD с вложенными запросами на синтаксический анализ   -  person nathan    schedule 30.08.2017
comment
Что вы хотите сделать после того, как все запросы будут выполнены? Связанный выше вопрос/ответ (второй) похож на то, что вы ищете, хотя API был немного обновлен в Swift 3.   -  person nathan    schedule 30.08.2017
comment
Не могли бы вы привести простой пример того, как это сделать с помощью GCD? Большое спасибо.   -  person Robert Marlan    schedule 30.08.2017


Ответы (1)


Вы можете использовать DispatchGroups, вот пример (взято из https://medium.com/@wilson.balderrama/how-to-use-dispatchgroup-gdc-with-swift-3-35455b9c27e7. Аналогично GCD с вложенными запросами Parse, но обновленный до Swift 3 API):

// Just a sample function to simulate async calls
func run(after seconds: Int, closure: @escaping () -> Void) {
    let queue = DispatchQueue.global(qos: .background)
    queue.asyncAfter(deadline: .now() + .seconds(seconds)) {
        closure()
    }
}

let group = DispatchGroup()

group.enter()
run(after: 6) {
    print("Hello after 6 seconds")
    group.leave()
}

group.enter()
run(after: 3) {
    print("Hello after 3 seconds")
    group.leave()
}

group.enter()
run(after: 1) {
    print("Hello after 1 second")
    group.leave()
}


group.notify(queue: DispatchQueue.global(qos: .background)) {
    print("All async calls were run!")
}

Используя ваш код:

let group = DispatchGroup()

for srcTerm in sFields {  //search using all search fields
    group.enter()
    multiQuery (searchTerm: srcTerm) {
        if srResult.count < self.lastValue {
            self.lastValue = srResult.count
            self.lastSearch = srcTerm
        }
        group.leave()
    }
}

group.notify(queue: DispatchQueue.global(qos: .background)) {
    // Do something after all async calls are done
}
person nathan    schedule 30.08.2017
comment
Спасибо Натан! Я не понимал, что это так просто. Спасибо. - person Robert Marlan; 30.08.2017