1

I have a couple of operations to perform on the IoT device from iOS App. So All my operations are in OperationsQueue with serial operations.

Here I want to perform one operation at a time and each operation needs to wait until I get a response from the IoT device.

Here IoT device response will take time to send back. so how to wait for the current operation in operation queue until I get a response from IoT.

So is there any way to pause current running operation until getting a response from IoT and then I will resume it so that the next operation in operation queue will start.

I tried with Sleep operation But it required time, but we can not guarantee about IoT device response.

Any suggestions would appreciate it. Thank you in advance.

srinadh
  • 123
  • 3
  • 11

3 Answers3

3

The basic idea is that you don’t pause (or wait, or sleep), but rather you define a “concurrent” operation (see discussion of concurrent operations in the documentation) that doesn’t trigger the isFinished KVO until the device responds.

A simple way to do this is to write a concurrent operation class, like the one shown in this answer. Then your IoT operation can subclass that AsynchronousOperation class, and just call finish() when the device responds.

Then your operation queue (which presumably has a maxConcurrentOperationCount of 1, or perhaps is using dependencies), will not start an operation until the prior operation has finished.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
2

As Rob said, you can implement Asynchronous Operation class and subclass from it your IoT operation. For me it looks like the most preferred way to implement yr case.

As an alternative, in cases where you need to continue the process only after some asynchronous event in another thread completed, you can use NSCondition. This is a mechanism from obj-c that provide an easy way to wait for a condition to occur.

Here is example:


let cond = NSCondition()
var available = false
var sharedString = ""

class WriterThread: Thread {

    override func main() {
        for _ in 0..<5 {
            cond.lock()
            sharedString = ""
            available = true
            cond.signal() // Notify and wake up the waiting thread/s
            cond.unlock()
        }
    }
}

class PrinterThread: Thread {

    override func main(){
        for _ in 0..<5 { //Just do it 5 times
            cond.lock()
            while(!available) {   //Protect from spurious signals
                cond.wait()
            }
            print(SharedString)
            sharedString = ""
            available = false
            cond.unlock()
        }
    }
}

let writet = WriterThread()
let printt = PrinterThread()
printt.start()
writet.start()

V.V.V
  • 235
  • 1
  • 13
1

You could use a DispatchQueue and call .suspend() when you send the operation, and have the code that gets the response call .resume(). Then wherever you want to wait for the response before continuing, just put a dummy queue.sync({ print("done waiting")}) and it will automatically wait until .resume() has been called before printing and continuing.

import Dispatch
var queue = DispatchQueue(label: "queue")

func sendOperationToIoTDevice(){
    //send the operation
    //...
    queue.suspend()
}

...

//whatever code gets the response:
    //get response
    //...
    queue.resume()

...

//main code

sendOperationToIoTDevice()
queue.sync { print("done waiting") } // will hang here until .resume() is called
Porter Child
  • 132
  • 1
  • 5