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.
- ViewController instantiates NSOperation subclass (which encapsulates URL, parameters etc)
- NSOperation subclass instanciates NSURLConnection (which performs synchronous request and retrieves data)
- NSURLConnection dumps data to NSOperation-subclass
- NSOperation-subclass 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.
What I did - is just allow
Operation
andURLSessionTask
remain separately. For doing this I made general purpose asynchronous block operation which is used to instantiate, resume, cancelURLSessionTask
.So, in ViewController or Data layer I'm still using chained
Operations
withURLSessionTasks
inside. Sample code below can be extended by subclassingAsynchronousBlockOperation
.File 1. Generic asynchronous operation.
File 2. Asynchronous block based operation:
File 3. Protocols
Usage:
You can use the same pattern, replacing
NSURLConnection
withNSURLSessionTask
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 aNSURLSession
. (NSURLSession
is theNSURLSessionTask
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 aNSURLSession
or enough information to create their own.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 toNSURLSession
, but if you do, you will lose certainNSOperation
functionality (dependencies, controlling degree of concurrency, etc.). I'm not sure why you'd want to excise operations from your code as you transition toNSURLSession
. Personally, anywhere I used to wrap aNSURLConnection
in an operation, I now wrap aNSURLSessionTask
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 theNSURLSession
). (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-basedNSURLSession
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/NetworkManagerThis is not intended to be a complete solution, but illustrates the idea of how you might implement a delegate-based
NSURLSession
withNSOperation
subclasses.What you are describing is
NSURLRequest
. BothNSURLSession
andNSURLConnection
takeNSURLRequest
s to perform network connections (theNSURLRequest
is what it's performing). What you seem to want is a set of factory methods for generating different, specializedNSURLRequests
. For example, one that describes the "get my mail" request. You can do this easily by creating a category onNSURLRequest
itself. Example:Create something similar to the above that meets your needs. The resulting
NSURLRequest
s can then be used to create connections. In Cocoa this is a very typical pattern for customizing objects, instead of subclassing. Subclassing is pretty rare - instead Cocoa has other mechanisms for customizing class behavior, from factory methods ("convenience methods" like the above) to delegation (where an object is given responsibility for the behavior of another object).