NSURLConnection.sendAsynchronousRequest
and
dispatch_async(dispatch_get_main_queue()) {}
I see that one is specific to urlRequests but could one have also used the dispatch_async function to get a data from URL then do UI related stuff in an asynchoronous fashion?
Thanks in advance,
Ace
Like you said the NSURLConnection method is specifically for sending async request and acts at a higher level of abstraction. Meaning a lot of heavy lifting is done for you under the hood.
Also what you do in the example is dispatching the call of the block you would supply asynchronously, but the block itself would be executed on the main queue, which would not be asynchronous.
You could for example download something in the background with the asynchronous request and then do UI related stuff on the main queue with your dispatch_async call.
So to speak: dispatch_async is part of the rather low-level GCD framework that can be used for a variety of things, like dispatching arbitrary codeblocks on different queues etc. See here for reference
Related
I have a swift class that does runs a multi-step process, much like this question has: Simple GCD Serial Queue example like FIFO using blocks
So i have a single public method of func start(), then a bunch of private methods which contain each "step" of the process.
I've spoken to a few people about this and i've been told i don't need to use a load of completion handlers and can instead use a serial dispatch queue.
However, if some of those steps run something that contains its own queue, then the method will end (and the next step starts) before it really has completed. So for example if func step1() uses Alamofire to download some data from an API, and step2() turns the response json into data models, step1() will return before the network response comes in. This is why i originally used callbacks, however i'm being told i don't need them?
The only way i can see a serial queue working is if there was a way of manually telling the queue when a certain task is complete (which there isn't?).
Could anyone help me work out the best way to structure and run this multi-step process, preferably without a load of nested completion handlers?
Or in other words: How do you use serial dispatch queues if some of the tasks you push to the queue will do things like network requests that return immediately.
You can use NSOperationQueue for that. NSOperationQueue is built on top of GCD and specially designed to manage a number of dependent jobs.
I'm developing a network based iOS app that downloads json data from the server and processes it. Both the downloading task and processing task can take a significant time to complete, So I don't want to perform either on the main thread.
I think there are 2 ways to do this:
Perform asynchronous loading using NSURLConnection and in the didFinishLoading method use GCD (say) to do the processing in background.
Use GCD's dispatch_async (say) to start work in background and use NSURLConnection's sendSynchronousRequest:returningResponse:error to download the data synchronously, Do the processing of the data, And call UI updates on the main thread.
I think the 2nd method would be easier to write and would produce cleaner code, Especially if one "download/process data" task involves multiple sequential service calls for data download. So rather than execution going like:
main (start) -> background (download) -> main (NSURLConnectionDelegate method) -> background (data processing) -> main (UI update)
We would have:
main (start) -> background (download) -> background (data processing) -> main (UI update)
which seems to be cleaner to me.
I found 2 similar questions: Good pattern for Internet requests with Grand Central Dispatch?
And
NSURLConnection and grand central dispatch
And the answers to both seem to suggest using something conceptually similar to method 1.
Is there no proper way to achieve what's described in method 2?
Thanks in advance!
I would not be inclined to pursue option #2. Although it enjoys a certain simplicity, sendSynchronousRequest does not afford progress updates during the download, the ability to cancel the request (and other more complicated scenarios). A NSURLConnectionDataDelegate approach gives you far more control over the network requests.
This question presumes GCD-based patterns, but I think operation queue patterns merit consideration. You can marry the control offered by the NSURLConnectionDataDelegate methods with cancelable operations that encapsulate the network request. When you start to get more sophisticated, you can start employing concurrent requests, but also constrain the degree of concurrency (e.g. not more than five concurrent requests).
I'd suggest taking a look at AFNetworking. Maybe you don't want to use that framework, but I'd still take a look at the operation-queue-based patterns it employs. I'd personally use that pattern over either of the aforementioned GCD approaches.
I am doing a lot of GCD and asynchronous rendering and data retrieval work lately and I really need to nail the mental model about how asynchronous is done.
I want to focus on setNeedsDisplay and the NSURLConnectionDelegate suite of methods.
Is it correct to call setNeedsDisplay asynchronous? I often call it via dispatch_async(dispatch_get_main_queue(), ^{}) which confuses me.
The NSURLConnectionDelegate callbacks are described as asynchronous but are they not actually concurrently run on the main thread/runloop. I am a but fuzzy on the distinction here.
More generally in the modern iOS era of GCD what is the best practice for making GCD and these methods play nice together. I'm just looking for general guidelines here since I use them regularly and am just trying not to get myself in trouble.
Cheers,
Doug
No, you generally don't call setNeedsDisplay asynchronously. But if you're invoking this from a queue other than the main queue (which I would guess you are), then you should note that you never should do UI updates from background queues. You always run those from the main queue. So, this looks like the very typical pattern of dispatching a UI update from a background queue to the main queue.
NSURLConnection is described as asynchronous because when you invoke it, unless you used sendSynchronousRequest, your app immediately returns while the connection progresses. The fact that the delegate events are on the main queue is not incompatible with the notion that the connection, itself, is asynchronous. Personally, I would have thought it bad form if I can some delegate methods that were not being called from the same queue from which the process was initiated, unless that was fairly explicit via the interface.
To the question of your question's title, whether NSURLConnection uses GCD internally, versus another concurrency technology (NSOperationQueue, threads, etc.), that's an internal implementation issue that we, as application developers, don't generally worry about.
To your final, follow-up question regarding guidelines, I'd volunteer the general rule I alluded to above. Namely, all time consuming processes that would block your user interface should be dispatched to background queue, but any subsequent UI updates required by the background queue should be dispatched back to the main queue. That's the most general rule of thumb I can think of that encapsulates why we generally do concurrent programming and how to do so properly.
What is the differance between adding a operation which make a synchronous NSURLConnection request in NSOperationQueue ( or synchronous request from a thread ( not main thread)) AND making a asynchronous request from the main thread ?
Both will not block main thread so UI will remain responsive but is there any advantage of using one over other? I know in later method i can track request progress etc but assume that progress and other HTTP stuff is not important here.
They are very similar. The biggest problem with synchronous requests is that they can't easily be cancelled. Depending on your application, that could be a problem. Imagine you are downloading a big document and the user moves to another screen so you no longer need that information. In our case, I actually chose doing asynchronous NSURLConnections on a secondary NSThread, which may be overkill for some apps. It is more complicated, but it gives us the ability to both cancel requests and to decode the JSON/XML/image data on secondary threads so they don't impact main thread user interactivity.
Asynchronous requests are scheduled on the run loop and setup as a run loop source, triggering the code automatically only when there is data received from the network (as any socket source).
Synchronous requests running on a NSThread monopolizes a thread to monitor the incoming data, which is in general quite overkill.
You can always cancel an NSURLConnection even if it has been executed asynchronously, using the cancel method.
I bet using the new API that allows to send an asynchronous request on an NSOperationQueue (+sendAsynchronousRequest:queue:completionHandler:) uses GCD under the hood and dispatch_source_create, or something similar, so that it behave the same way as when an NSURLConnection is scheduled on the run loop, avoiding using an additional thread (watch the WWDC'12 videos that explains why threads are evil and their usage should be minimized), the difference only being that allows you to use a block to be informed upon completion instead of using the delegate mechanism.
Some years ago I created a class that embedded NSURLConnection asynchronous calls and delegate management into a nice block API (see OHURLLoader on my github) that makes it easier to use (feel free to take a look). I bet the new API that uses NSOperationQueues uses the same principle, still doing asynchronous requests on the runloop but allowing you to use blocks instead of having to implement a delegate.
The historical position was that there's an advantage in power consumption, and therefore battery life, in asynchronous requests — presumably including both the older delegate approach and the new block-based approach.
Can someone explain the relationship between asynchronous NSURL requests and GCD and NSOperationQueues?
I am not sure when to use each.
Right now, I have been "getting away" with asynchronous NSURL requests when I need to fetch/upload data to the server. But it has been suggested that I should use GCD. My problem is I do not know in what real life examples GCD would be better. Does anyone have any common use cases for me? And if I use GCD to store a queue of 10 asynchronous NSURL GET requests, for example, how would this benefit me? Does it even make sense to have an asynchronous NSURL request inside grand central dispatch queue or an NSOperationQueue?
Thank you!
What is particularly confusing in your case is that we're mixing an HTTP request queue (where requests would be sent one after the other) and an operation queue (where random computational work is executed one task after the other).
A standard NSURLConnection instance calls its delegate on the main thread, which is OK if you're not doing complex work on the data or on your UI at that time. But say you need to download a big file and write it chunk by chunk as a file on disk, all while scrolling down a table view. Now your scrolling might get choppy when you write data on the disk, blocking the main thread.
That's where GCD or its higher level abstraction NSOperationQueue comes into play. To solve this issue, you need to offload your data write calls off of the main thread. You can do that by specifying an NSOperationQueue instance on your NSURLConnection via setDelegateQueue:. This will ensure your delegate, and therefore your write calls, will be called in a background thread. You can also leave the delegate calls on the main thread, and wrap your expensive write calls inside a block which you will then execute off the main thread with dispatch_async. Now NSOperationQueue basically wraps a dispatch queue, and you're avoiding an extra thread switch by using it over a raw dispatch queue so I would recommend the NSOperationQueue solution (which also happens to looks simpler).
AFNetworking is a great library, and it solves this issue in a third way: it fires off an NSThread which is dedicated to NSURLConnection delegate calls. That's the pre-GCD way of offloading work off the main thread. Although it works, GCD offers a more efficient and good-citizen way of presenting your background work to the system.
Last, if you're looking for an HTTP request queue, Cocoa doesn't provide it. You will have to either build a scheduler yourself, or as you already figured it out use AFNetworking which again is a great choice.
If you're interested in this topic, GCD has a lot more to offer than just hosting NSURLConnection delegate calls, and I would recommend you read Apple's great Concurrency Programming Guide or watch the excellent WWDC 2011 videos on GCD (Blocks and Grand Central Dispatch in Practice and Mastering Grand Central Dispatch).
This is off the topic but if you use AFNetworking Lib you dont have to do anything you mentioned above.
"AFNetworking is a delightful networking library for iOS and Mac OS X. It's built on top of NSURLConnection, NSOperation, and other familiar Foundation technologies. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use. "
Answer to your question, please read this
http://www.cocoaintheshell.com/2011/04/nsurlconnection-synchronous-asynchronous/