SteveSmith SteveSmith - 7 months ago 16
Swift Question

How does a callback/closure know to wait after Asynchronous call is finished?

I am new to Swift and have a question concerning callbacks/closures. During a Asynchronous network call different items come at different times. I would like to know how a callback knows not to get executed until everything we are looking for from the request in returned?

EDIT:

dispatch_async(dispatch_get_main_queue(), {
//Array to store HingeImage objects
var myImageArray = Array<HingeImage>()

for items in parsedResult {

//Create custom objects with values needed
let finalObjects = HingeImage(dictionary: items as! [String : AnyObject])

myImageArray.append(finalObjects)

}

// Callback completion
callback(hingeImages: hingeImageArray, error: nil)
})


EDIT 2 :

class SecondViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.

callTheCallBackAndGrabData()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

func callTheCallBackAndGrabData() {

MainVC.requestWithCallback { (hingeImage, error) in
print(hingeImage)

}
}
}

Answer

To understand closures and how they work one must understand that they are simply variables as Int or String, but they also have return value, most commonly Void. In a nutshell they allow you to wrap a block of code into single variable you can call later in the code.

Let's take a look at a simple closure definition:

let simpleClosure: (Int -> Void) = {
     intValue in   
     print("Number is \(intValue)")
}

You can see that closure is instance like any Int or String, but with return type, in this case Void or ().

All closures are defined in { } braces with input values defined first (in this case it is intValue). This intValue will come from the Int parameter in closure definition. Let's see how we can call this closure.

simpleClosure(5)

This will print following:

// Number is 5

What happened here is that number 5 is passed to the Int closure parameter and you get it through intValue variable as described above. Since we are returning Void we don't need to write return statement and the closure finished execution.

Now to the question, closure doesn't know automatically when it is executed, rather it is called when some task is executed. Asynchronous network calls is pretty much the same. You perform network task synchronously (on low level TCP protocol) and notify the programmer when the task is finished via closure. This is the example of how it may be implemented:

func networkRequest(url: String, closure: (NSData?,ErrorType?) -> ()) {
    runRequest(url)
    let response = getServerResponse()
    closure(response.data, response.error)
}

To summarize up, it's up to programmer to decide when closure is executed and that operation does not happen automatically.