Как запустить синхронно две функции с асинхронными операциями в 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)
}