-1

In Swift (that's Swift) there are a number of ways to handle asynchronous,

Say you have a loop like this - it's calling a parse cloud code call which goes to background anyway.

public func runImages()
   {
   print("test begins...")
   for i in 1...3
      {
      print("Tick tock tick tock ..\(i)")
      PFCloud.callFunctionInBackground("blah", withParameters:["bla":i,"bla":"bla] )
         {
         (response: AnyObject?, error: NSError?) -> Void in
          print(".. done! Now go again...")
          if let rr = response as? String { print(rr) }
          if let err = error { print(err.domain) }
         }
      }
   }

How to make that wait for the end of each PFCloud call?

Really is just an ordinary flag best, or? (Note that (a) I can't get a flag to work in Swift and (b) as Paul points out you're blocking the UI!!)

What is the "Swift way" in the context you see here? I feel it would be very inelegant to use a recursive pattern here, for example.

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • Don't "wait". Simply execute the code that you want in the closure. If you want the cloud code functions to execute serial the you need to dispatch them onto a serial dispatch queue and use `callFunctuon` rather than `callFunctionInBackground` – Paulw11 Sep 25 '15 at 00:23
  • Hi Paul - the code above will run all three calls at the same time (synchronously). Often, you do not want this: you want them to run one after the other. One only begins when another one ends. – Fattie Sep 25 '15 at 00:33
  • You could use a `dispatch_barrier_async` on the serial dispatch queue if you wanted to submit a block that would execute after all three methods had completed – Paulw11 Sep 25 '15 at 00:33
  • That is why I said you would need to dispatch the synchronous equivalent on a serial dispatch queue – Paulw11 Sep 25 '15 at 00:33
  • Hi Paul, understood, but it seems a shame to go to the synchronous Parse methods. It would be very natural to just wait on a flag for example. Actually how can you use a blocking flag `while(wait){}` in Swift, do you know? I notice that if you use a normal property it does not seem to work / does not check it. – Fattie Sep 25 '15 at 00:44
  • You can't wait in that way because you will block the main queue and freeze your UI. Even though you are using synchronous Parse calls, execution is still asynchronous from the main queue because it is dispatched on another queue - see my answer – Paulw11 Sep 25 '15 at 00:46
  • Ah yes of course you'd be blocking the main queue. (Funnily enough I was just writing a sort of utility program, to run on my iPhone simulator - not an actual app!) But wait, can't you do what I say with a semaphore?? http://stackoverflow.com/a/21787509/294884 – Fattie Sep 25 '15 at 01:02
  • No matter how you block you are going to be blocking the main queue. And that will synchronise two tasks but it won't give you the serial execution of the three tasks with a final synchronisation. – Paulw11 Sep 25 '15 at 01:02
  • gotchya .. makes good sense. – Fattie Sep 25 '15 at 01:04
  • possible duplicate of [How to tell if blocks in loop all have completed executing?](http://stackoverflow.com/questions/23253175/how-to-tell-if-blocks-in-loop-all-have-completed-executing) – David Berry Sep 25 '15 at 01:26

1 Answers1

2

If you want the three calls to execute serially then you can use a serial dispatch queue and a dispatch_barrier_async to do something when all three are finished -

let dispatchQueue=dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL)

for i in 1...3 {
    dispatch_async(dispatchQueue, { () -> Void in
        print("i=\(i)")
        let result = PFCloud.callFunction("blah", withParameters:["bla":i,"bla":"bla] )
    })
}

dispatch_barrier_async(dispatchQueue, { () -> Void in
    print("really done")
})

print(" done")

In order for this to work with your Parse function you need to use the synchronous cloud code call, not an asynchronous. And if you update UI in the dispatch_barrier_async closure you would need to dispatch that on the main queue.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • thanks for the fantastic example code, in Swift, fantastic. I would also kind of like to find a way to do it using parse's usual background calls .. am still looking! – Fattie Sep 25 '15 at 01:03
  • You can't use Parse's background calls because then you can't really synchronise because you have "lost control" – Paulw11 Sep 25 '15 at 01:04
  • I guess I shouldn't say "can't" but rather "shouldn't" as you have to engineer a synchronisation solution that GCD can give you "for free" – Paulw11 Sep 25 '15 at 01:42
  • Thanks. I can't imagine how I learned to program in the 80s without the Internet to provide instant answers :) – Paulw11 Sep 25 '15 at 11:00