Do I Need to Wrap My Alamofire Calls Inside Dispatch_Async

Do I need to wrap my Alamofire calls inside dispatch_async?

Alamofire is designed to be asynchronous. On another note, if the method has as callback, most likely it is asynchronous.
So, yes you can leave out the dispatch_async calls.

How to make sure that an Alamofire request runs?

We need to do two things.

  1. Execute the request in the background.
  2. Block the main thread until the request is done, i.e. the completion handler ran.

My original code does neither.

The first item is achieved by using .response(queue: DispatchQueue(label: "some-name")) (or one of its variants).

Waiting can be done in several ways.

  1. Using a flag and active waiting, as shown here (won't scale to more than one request).
  2. Use active waiting with countdown latch as shown here (works for multiple requests).
  3. Use DispatchSemaphore as seen e.g. here.

And probably many more.

iOS - Asynchronous requests and UI interactions

Alamofire networks asynchronously. No worries there. The problem, though, is probably here:

let url = NSURL(string: image["unescapedUrl"] as! String)!
if let data = NSData(contentsOfURL: url) {

If, as I suspect, that URL is a remote URL, then you are now repeatedly networking synchronously. NSData(contentsOfURL:) is not appropriate for fetching stuff across a network on the main thread. If you're going to reach out for more data on the network, use proper networking code - perhaps even using Alamofire some more...

AFNetworking 2 + SwiftyJSON

First of all, you don't need to dispatch to the main queue. AFNetworking already calls these blocks on the main thread.

The initializer you're using is expecting data, not a JSON object.

You're currently using this initializer, which expects an NSData:

let json = JSON(data: dataFromNetworking)

Instead, you should be using this initializer:

let json = JSON(jsonObject)

SwiftyJSON will work fine if you pass responseObject here.


One other note: this code doesn't belong in the completion blocks. In AFNetworking's design, you should be creating a response serializer that handles the server's response. I recommend looking at the source for AFJSONResponseSerializer and porting that over to use SwiftyJSON.

How to perform segue after information from protocol is recieved

The other responders have hinted about this, but haven't stated it explicitly, so here goes.

Do not tie a segue directly to the button. Instead, control-drag from the source view controller SCENE to the destination scene to create a segue at the view controller level. Give the segue a unique identifier.

Then, in your button IBAction code, do the async network download. You may want to display a "loading, please wait" message or something while the download is taking place. Most async network calls take a completion block. In that completion block, wrap a call to performSegueWithIdentifier in a call to dispatch_async(dispatch_get_main_queue() so the segue gets invoked on the main thread. (@SantaClaus's answer shows the syntax for that.)

So your button IBAction code might look like this:

- (IBAction) buttonAction: (UIButton *) sender;
{
//Display a "please wait"message to the user if desired
doAsyncCallTakingBlock( completion: ^(NSData *data)
{
//parse the data, (or whatever)

dispatch_async(dispatch_get_main_queue(), ^
{
//This call uses the button as the sender. That might be appropriate,
//or not.
[self performSegueWithIdentifier:@"jumpToOtherViewController"
sender: sender];
});
}
}

With this approach the segue doesn't get called until the async method (Which I called doAsyncCallTakingBlock in my example code) has finished it's work. You might call an Alamofire request method, use an NSURLSession, or any other async method that takes a completion block.



Related Topics



Leave a reply



Submit