Having used the AlamoFire framework I've noticed that the completionHandler is run on the main thread. Im wondering if the code below is a good practice for creating a Core Data import task within the completion handler:
Alamofire.request(.GET, "http://myWebSite.com", parameters: parameters) .responseJSON(options: .MutableContainers) { (_, _, JSON, error) -> Void in dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { () -> Void in if let err = error{ println("Error:\(error)") return; } if let jsonArray = JSON as? [NSArray]{ let importer = CDImporter(incomingArray: jsonArray entity: "Artist", map: artistEntityMap); } }); }
Everything with Alamofire is asynchronous, which means you'll update the UI in an asynchronous manner: Hide the upload button, and show the progress view and activity view. While the file uploads, you call the progress handler with an updated percent.
Alamofire is a networking library written in Swift. You use it to make HTTP(S) requests on iOS, macOS and other Apple platforms. For example, to post data to a web-based REST API or to download an image from a webserver. Alamofire has a convenient API built on top of URLSession (“URL Loading System”).
This is a really good question. Your approach is perfectly valid. However, Alamofire can actually help you streamline this even more.
In you example code, you are jumping between the following dispatch queues:
As you can see, you're hopping all over the place. Let's take a look at an alternative approach leveraging a powerful feature inside Alamofire.
Alamofire has an optimal approach built into it's own low level processing. The single response
method that ultimately gets called by all custom response serializers has support for a custom dispatch queue if you choose to use it.
While GCD is amazing at hopping between dispatch queues, you want to avoid jumping to a queue that is busy (e.g. the main thread). By eliminating the jump back to the main thread in the middle of the async processing, you can potentially speed things up considerably. The following example demonstrates how to do this using Alamofire logic straight out-of-the-box.
let queue = dispatch_queue_create("com.cnoon.manager-response-queue", DISPATCH_QUEUE_CONCURRENT) let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"]) request.response( queue: queue, serializer: Request.JSONResponseSerializer(options: .AllowFragments), completionHandler: { _, _, JSON, _ in // You are now running on the concurrent `queue` you created earlier. println("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())") // Validate your JSON response and convert into model objects if necessary println(JSON) // To update anything on the main thread, just jump back on like so. dispatch_async(dispatch_get_main_queue()) { println("Am I back on the main thread: \(NSThread.isMainThread())") } } )
let queue = dispatch_queue_create("com.cnoon.manager-response-queue", DISPATCH_QUEUE_CONCURRENT) let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"]) request.response( queue: queue, responseSerializer: Request.JSONResponseSerializer(options: .AllowFragments), completionHandler: { response in // You are now running on the concurrent `queue` you created earlier. print("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())") // Validate your JSON response and convert into model objects if necessary print(response.result.value) // To update anything on the main thread, just jump back on like so. dispatch_async(dispatch_get_main_queue()) { print("Am I back on the main thread: \(NSThread.isMainThread())") } } )
let queue = DispatchQueue(label: "com.cnoon.response-queue", qos: .utility, attributes: [.concurrent]) Alamofire.request("http://httpbin.org/get", parameters: ["foo": "bar"]) .response( queue: queue, responseSerializer: DataRequest.jsonResponseSerializer(), completionHandler: { response in // You are now running on the concurrent `queue` you created earlier. print("Parsing JSON on thread: \(Thread.current) is main thread: \(Thread.isMainThread)") // Validate your JSON response and convert into model objects if necessary print(response.result.value) // To update anything on the main thread, just jump back on like so. DispatchQueue.main.async { print("Am I back on the main thread: \(Thread.isMainThread)") } } )
Here is the breakdown of the different dispatch queues involved with this approach.
By eliminating the first hop back to the main dispatch queue, you have eliminated a potential bottleneck as well as you have made your entire request and processing asynchronous. Awesome!
With that said, I can't stress enough how important it is to get familiar with the internals of how Alamofire really works. You never know when you may find something that can really help you improve your own code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With