I've been traditionally using a pattern where NSOperation subclasses create and manage their own NSURLConnection. The NSOperation subclass is instantiated by the view controller and will do its work without bothering the controller until it has finished. When it finishes retrieving data, it executes the completion block supplied by the view controller.
I'm trying to implement the same pattern with NSURLSession now. I want to be able to encapsulate the url and parameters required to make a network request inside a single object. Do I achieve this using NSURLSession subclasses or NSURLSessionTask subclasses?
I like to create separate classes for every network operation based on the actor design pattern.
The NSURLSessionTask
class (and its subclasses) look a bit like operations, but they're not. Thus, you can remove operations from your code as you transition to NSURLSession
, but if you do, you will lose certain NSOperation
functionality (dependencies, controlling degree of concurrency, etc.). I'm not sure why you'd want to excise operations from your code as you transition to NSURLSession
. Personally, anywhere I used to wrap a NSURLConnection
in an operation, I now wrap a NSURLSessionTask
with an operation.
As an aside, one of the significant annoyances with NSURLSession
, though, is that the task delegates are set at the session object. We can make guesses why Apple did that, but it has all sorts of unfortunate implications. Clearly you can get around this by using the block based factory methods for creating your tasks, but then you lose the richness of the delegate API, if you happened to need that.
The implication of this is that if using block-based task factory methods, wrapping the task in a concurrent NSOperation
subclass is fairly obvious. But, if using the delegate-based tasks, though, if you want custom handlers for the tasks, you have to go through some silliness with maintaining a mapping between task identifiers and the appropriate completion blocks (which I personally put in a session manager object that I used to wrap the NSURLSession
). (FYI, I believe an implementation like this is expected in a forthcoming AFNetworking update, too. See the latter part of the discussion on Issue 1504 on the AFNetworking github site.)
Anyway, others have answered the question how you could replace your operation-based NSURLConnection
code with non-operation-based NSURLSession
code, but I'd personally suggest staying with operations.
By the way, I've uploaded a example implementation of an operation-based NSURLSession
implementation on github: https://github.com/robertmryan/NetworkManager
This is not intended to be a complete solution, but illustrates the idea of how you might implement a delegate-based NSURLSession
with NSOperation
subclasses.
You can use the same pattern, replacing NSURLConnection
with NSURLSessionTask
subclasses (e.g. NSURLSessionDataTask
).
As @CouchDeveloper suggests in the comments, an alternative is to wrap NSURLSessionTask
in an non-NSOperation
object with asynchronous semantics (cancel, resume, etc.). This wrapper object would do little more than encode and decode parameters, delegating most operations to the wrapped task.
In either case, to instantiate NSURLSessionTask
, you will need a NSURLSession
. (NSURLSession
is the NSURLSessionTask
factory.) If all of your operations use the same configuration (cookies, proxy, caching, etc.), you can simply use the shared session (+[NSURLSession sharedSession]
). If they need different configurations, you'll have to give them a NSURLSession
or enough information to create their own.
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