Как запустить синхронно две функции с асинхронными операциями в iOS с помощью Swift
давайте предложим этот сценарий
метод с асинхронными сетевыми операциями
func asyncMethodA() -> String?
{
   result : String?
   Alamofire.manager.request(.POST, "https://www.apiweb.com/apimethod", parameters: parameters, encoding:.JSON)
            .response { (request, response, rawdata, error) in
                if (response?.statusCode == 200)
                {
                    //DO SOME HEAVY LIFTING
                }
        }
        return result //string
}
другой метод с async сетевых операций
func asyncMethodB() -> String?
{
   result : String?
   Alamofire.manager.request(.POST, "https://www.yetanotherapiweb.com/apimethod", parameters: parameters, encoding:.JSON)
            .response { (request, response, rawdata, error) in
                if (response?.statusCode == 200)
                {
                    //DO SOME HEAVY LIFTING
                }
        }
        return result //string
}
метод, в котором я буду называть эти методы A и B, чтобы сделать некоторые операции
func displayResult
{
   1)  let a = asyncMethodA()
   2)  let b = asyncMethodB()
   3)  println(a + b) //some chaotic stuff might happen :(
}
Итак, вопрос в том, как я мог бы сделать, чтобы (2) ждал (1) запуска, и (3) ждал (2) и так далее (что 1,2 и 3 запускаются синхронно)?
(Я знаю, что один ответ заключается в цепи asyncMethodA и displayResult в asyncMethodB, но хотите знать, есть ли какой-то другой метод)
спасибо!.
3 ответов
func anAsyncMethod(resultHandler: (result: AnyObject) -> Void) {
    ...        
}
func anotherAsyncMethod(resultHandler: (result: AnyObject) -> Void) {
    ... 
}
let operationQueue = NSOperationQueue()
func performWithCompletionHandler(completion: (AnyObject?, AnyObject?) -> Void) {
        var resultOfOperation1: AnyObject?
        var resultOfOperation2: AnyObject?
        let operation1 = NSBlockOperation {
                let dispatchGroup = dispatch_group_create()
                dispatch_group_enter(dispatchGroup)
                self.anAsyncMethod {
                        result in
                        resultOfOperation1 = result
                        dispatch_group_leave(dispatchGroup)
                }
                // wait until anAsyncMethod is completed
                dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER)
        }
        let operation2 = NSBlockOperation {
                let dispatchGroup = dispatch_group_create()
                dispatch_group_enter(dispatchGroup)
                self.anotherAsyncMethod {
                        result in
                        resultOfOperation2 = result
                        dispatch_group_leave(dispatchGroup)
                }
                // wait until anotherAsyncMethod is completed
                dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER)
        }
        let completionOperation = NSBlockOperation {
                // send all results to completion callback
                completion(resultOfOperation1, resultOfOperation2)
        }
        // configuring interoperation dependencies
        operation2.addDependency(operation1)
        completionOperation.addDependency(operation2)
        operationQueue.addOperations([operation1, operation2, completionOperation], waitUntilFinished: false)
}
С помощью ниже, вы можете запустить оба асинхронных методов в то же время и сделать ваш тяжелый подъем после того, какой из них заканчивается последним.
var methodAFinished = false
var methodBFinished = false
func asyncMethodA() -> String?
{
    Alamofire.manager.request(.POST, "https://www.apiweb.com/apimethod", parameters: parameters, encoding:.JSON)
        .response { (request, response, rawdata, error) in
            if (response?.statusCode == 200) {
                methodAFinished = true
                doStuff()
            }
        }
    return result //string
}
кишки asyncMethodB были бы methodBFinished = true; doStuff()
func doStuff() {
    if methodAFinished && methodBFinished {
        // do crazy stuff
    }
}
спасибо Yimin за код выше. Я обновил его до последнего синтаксиса Swift, поэтому просто публикую, чтобы быть полезным:
func anAsyncMethod(resultHandler: (_ result: AnyObject) -> Void) {
    ...
}
func anotherAsyncMethod(resultHandler: (_ result: AnyObject) -> Void) {
    ...
}
func performWithCompletionHandler(completion: @escaping (AnyObject?, AnyObject?) -> Void) {
    let operationQueue = OperationQueue()
    var resultOfOperation1: AnyObject?
    var resultOfOperation2: AnyObject?
    let operation1 = BlockOperation {
        let dispatchGroup = DispatchGroup()
        dispatchGroup.enter()
        self.anAsyncMethod {
            result in
            resultOfOperation1 = result
            dispatchGroup.leave()
        }
        // wait until anAsyncMethod is completed
        dispatchGroup.wait(timeout: DispatchTime.distantFuture)
    }
    let operation2 = BlockOperation {
        let dispatchGroup = DispatchGroup()
        dispatchGroup.enter()
        self.anotherAsyncMethod {
            result in
            resultOfOperation2 = result
            dispatchGroup.leave()
        }
        // wait until anotherAsyncMethod is completed
        dispatchGroup.wait(timeout: DispatchTime.distantFuture)
    }
    let completionOperation = BlockOperation {
        // send all results to completion callback
        completion(resultOfOperation1, resultOfOperation2)
    }
    // configuring interoperation dependencies
    operation2.addDependency(operation1)
    completionOperation.addDependency(operation2)
    operationQueue.addOperations([operation1, operation2, completionOperation], waitUntilFinished: false)
}
