2014-11-27 14 views
6

consente di proporre questo scenarioCome eseguire sincronicamente due funzioni con le operazioni asincrone su iOS che utilizzano Swift

un metodo con le operazioni di rete asincrone

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 

} 

un altro metodo con le operazioni di rete asincrono

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 
} 

un metodo in cui chiamerò quei metodi A e B, per fare alcune operazioni

quindi la domanda è come potrei fare che (2) aspetti (1) di correre, e (3) attenda per (2) e così via (che 1,2 e 3 corrano sincronizzati)?

(So che una risposta è quella di catena asyncMethodA e displayResult in asyncMethodB, ma voglio sapere se c'è qualche altro metodo)

grazie !.

+1

Sei consapevole che 'result' ritorno nelle funzioni asincrone viene eseguito * prima * i dati sono stati recuperati dalla rete? –

+0

Non sono nemmeno sicuro di dove viene dichiarato 'result'. –

+0

sì, non l'ho visto anche questo ... un altro problema haha, una possibile soluzione è usare una variabile globale e verificare se ha un valore diverso da zero, ma se si conosce una risposta per questa specifica istanza del problema, sarebbe molto apprezzato –

risposta

17
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) 
} 
+0

questa è la risposta che stavo cercando !, grazie mille Swipesight !. –

1

Con quanto riportato di seguito, è possibile avviare contemporaneamente entrambi i metodi asincroni e eseguire il sollevamento pesante dopo il termine ultimo.

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 
} 

viscere del asyncMethodB sarebbero methodBFinished = true; doStuff()

func doStuff() { 
    if methodAFinished && methodBFinished { 
     // do crazy stuff 
    } 
} 
+0

Pensavo che l'idea fosse che c'era qualcosa che volevi fare una volta * entrambe le * chiamate erano complete? Se vuoi fare qualcosa una sola chiamata è completa, metti la cosa nel blocco di risposta. –

+0

thx per la risposta, mm ok, questo è interessante ma quando doStuff viene chiamato se methodAFinished o methodBFinished sono ancora in esecuzione non succederà nulla, devo assicurare che A e B sono finiti per eseguire le operazioni successive ... non lo so se questo potrebbe essere in grado di realizzare usando GCD o chiusure ... im un principiante nel threading: S –

+0

oh vedo che proverò che thx –

0

Grazie Yimin per il codice precedente. Ho aggiornato alla più recente sintassi Swift quindi basta inviare per essere utile:

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) 
} 
Problemi correlati