1

I have a function I'm trying to make in Swift (X-Code). I'm basically sending a few commands over bluetooth and I have a question about how the Main Asyncafter works. Here's my set-up code:

func tPodSetUp()
    {
        var delayForResponse = DispatchTime.now() + 0.4 //seconds to wait for response
        writeValue(data: "231") //Put t-Pod in command mode, burst mode is OFF returns OK
        DispatchQueue.main.asyncAfter(deadline: delayForResponse)
        {
            if receivedString1.lowercased() == "ok"
            {
                print("t-Pod burst mode is OFF")
            }
        }

        writeValue(data: "202") //load calibration constants of probe, returns ok or 0
        DispatchQueue.main.asyncAfter(deadline: delayForResponse)
        {
            if receivedString1.lowercased() == "ok"
            {
                print("calibration Loaded")
            }
            if receivedString1 == "0"
            {
                print("No probe connected")
            }
        }
    }

I want it basically to do the following (IN THIS ORDER):
writeValue
wait .4seconds
read response / check response
writeValue (AFTER IT FINISHED READING/CHECKING RESPONSE)
read response /check response

I am afraid that if the code is as it is right now it will just overrun the writeValues while waiting for the other ones and will have them on separate threads running asynchronously.
Also, what's confusing me is the fact that I declared delayForResponse at the beginning, and say will this change every time it's called? like if I do it at 12:00:00:00 it will make it now + .4 seconds (so its supposed to be called at 12:00:00:40, but then what will happen at 12:00:00:41 when it runs the second part (that has another callout to delayForResponse) will it suddenly say "what? this was supposed to be done already .01 seconds ago!?

EDIT HEre's another take on the code based on some feedback, will this do what I think it will?

let setupQueue = DispatchQueue(label: "setupQueue")
    let delayForResponse = DispatchTime.now() + 0.4 //seconds to wait for response

setupQueue.sync {
    writeValue(data: String(UnicodeScalar(UInt8(231)))) //231: Put t-Pod in command mode, burst mode is OFF returns OK
    DispatchQueue.main.asyncAfter(deadline: delayForResponse)
    {
        if receivedString1.lowercased() == "ok"
        {
            print("t-Pod burst mode is OFF")
        }
    }

    writeValue(data: String(UnicodeScalar(UInt8(202)))) //202: load calibration constants of probe, returns ok or 0
    DispatchQueue.main.asyncAfter(deadline: delayForResponse)
    {
        if receivedString1.lowercased() == "ok"
        {
            print("t-Pod burst mode is OFF")
        }
        if receivedString1 == "0"
        {
            print("No probe connected")
        }
    }

    writeValue(data: String(UnicodeScalar(UInt8(204)))) //204: load t-Pod serial number
    DispatchQueue.main.asyncAfter(deadline: delayForResponse)
    {
        if (receivedString1.count > 5)
        {
            print("received t-Pod SN: \(receivedString1)")
            tPodSN = receivedString1
        }
    }

    writeValue(data: String(UnicodeScalar(UInt8(205)))) //205: load probe serial number
    DispatchQueue.main.asyncAfter(deadline: delayForResponse)
    {
        if (receivedString1.count > 3)
        {
            print("received Probe SN: \(receivedString1)")
            probeSN = receivedString1
        }
    }

    //AFTER FINISHING SETUP, RESET TPOD AND TURN BEACON OFF

    writeValue(data: String(UnicodeScalar(UInt8(202)))) //200: resets t-Pod
    writeValue(data: String(UnicodeScalar(UInt8(202)))) //211: turns beacon off (temperature output)
} 
dvd.Void
  • 339
  • 1
  • 5
  • 21

1 Answers1

3

Have you checked DispatchGroup ??

func myFunction() {
    var a: Int?

    let group = DispatchGroup()
    group.enter()

    DispatchQueue.main.async {
        a = 1
        group.leave()
    }

    // does not wait. But the code in notify() is run 
    // after enter() and leave() calls are balanced

    group.notify(queue: .main) {
        print(a)
    }
}
casillas
  • 16,351
  • 19
  • 115
  • 215
  • 1
    Beat me to it. This is what I would do. – Charles Srstka Sep 26 '17 at 19:47
  • Hi, I read a little about dispatch groups but it seems that it runs them in parallel, I do NOT want to run in parallel, I want them to run SEQUENTIAL. The main reason is that as you can read from my code I read from receviedString1. This has the response from the BLE peripheral, if I send it another command before reading its response I might be reading the response to something else which is what I want to avoid – dvd.Void Sep 26 '17 at 20:02
  • check this https://stackoverflow.com/questions/37805885/how-to-create-dispatch-queue-in-swift-3 – casillas Sep 26 '17 at 20:05
  • Hi, I edited my top code, will that work as I explained earlier? – dvd.Void Sep 27 '17 at 15:30
  • @dvd.Void You can use the dispatch groups to achieve this. Look at the example above. It's the same problem that you have; there's a variable `a` that needs to be written to before it is printed. Because of the dispatch group, the `print(a)` line will not be called until after the `a = 1` line is called. – Charles Srstka Sep 27 '17 at 15:56
  • Hi Charles, thanks for the reply, I guess what I'm missing is the sequence of commands, or I don't really understand, how would i go about assigning a, printing a and then assigning a another value and printing the new value (in sequence). I guess the example is oversimplified since it only has 1 command in queue and I can't really put it together – dvd.Void Sep 27 '17 at 16:22
  • @CharlesSrstka, I added a new question/code based on dispatch groups. I hope I am doing it correctly (however I'm having issues still). https://stackoverflow.com/questions/46478041/dispatchgroup-wait-not-waiting – dvd.Void Sep 28 '17 at 20:50