Your question is distorted. Your sample code is invalid and does not display a completion handler.
I suspect that you misunderstood how asynchronous requests and completion handlers work. Here is the sequence.
- Call a function and provide a completion handler
- The function returns immediately, and while in future creatures that execute the request
- The next line after the completion of the launch handler until the request even starts processing. The application continues to work. There is no result because the request is not yet complete.
- Asynchronous request ends. The original method calls the completion handler. NOW the result is available in the completion handler code. The completion handler code does everything necessary to process the results.
Here is a realistic example of how an asynchronous process can work with completion handlers: (You can find a working Xcode project that demonstrates this code on Github in this link )
First, the AsyncManager class, which simulates downloading an image from the Internet:
class AsyncManager { static let sharedAsyncManager = AsyncManager() func asyncFetchImage(#imageName: String, completion: (image: UIImage?, status: String) -> ()) { println("Entering \(__FUNCTION__)")
This is a singleton. It has a static let sharedAsyncManager that you use to get one instance of AsyncManager.
AsyncManager provides one asyncFetchImage method that takes an image name and a completion block. The function does not return any result, because it returns immediately before the image is loaded.
The code does not actually download the image from the Internet. Instead, it simply launches the GCD dispatch_after call to wait 3 seconds before loading the image and calling the completion block.
Now I create the ViewController class and give it the "Load Image" button. I am creating an IBOutlet theImageView for a UIImageView that will display the image I'm about to load.
I am writing an IBAction method for a Load Image button. Here's what this IBAction looks like:
@IBAction func loadImage(sender: UIButton) { let theAsyncManager = AsyncManager.sharedAsyncManager println("about to call asyncFetchImage") theAsyncManager.asyncFetchImage(imageName: "wareto_blue_150x115") { (image, status) -> () in println("Beginning completion block") self.theImageView.image = image println("In completion block, status = \(status)") } println("After call to asyncFetchImage") } }
Now, the fun part. Here's the sequence of events:
I click the loadImage button. The IBAction method is executed.
It gets a link to the async download manager syntax.
Displays a message, then calls the AsyncManager.asyncFetchImage method. The AsyncManager.asyncFetchImage method displays a recording message, queues a call to load an image after 3 seconds, displays a βleaveβ message and returns before the image is loaded . There is nothing to return because the image loading code is not already running.
The View controller's loadImage method displays the message "After calling asyncFetchImage" and returns.
After a few seconds, the code inside asyncFetchImage is executed. It displays a message, loads an image, and then calls the completion handler.
Here is the set of messages that you return when you run the above code:
about to call asyncFetchImage Entering asyncFetchImage(imageName:completion:) Leaving asyncFetchImage(imageName:completion:) After call to asyncFetchImage Loading image in background About to call completion handler Beginning completion block In completion block, status = image loaded
Notice that the last line is loadImage IBAction:
println("After call to asyncFetchImage")
displays a message until a message about loading the image appears. The code call for asyncFetchImage returns immediately before any work is done. The code after calling asyncFetchImage runs further, but the image is still not loaded. There is no way to return the result at this point, because the image loading has not yet begun.