NSURLSession and related classes provide an API for downloading data over the HTTP protocol. This class provides a number of proxy methods to support authentication and background downloads (when the program is not running or suspended).
To use NSURLSession, our application creates a series of sessions, each of which coordinates the transfer of a set of related data. In each session, our application adds a series of tasks, each representing a request to a specified URL. Like most networking apis, the NSURLSession API is asynchronous. If we use a system-provided broker, we must provide a request completion processing block to return data to our application if the request succeeds or fails. If we provide custom proxy objects, the task object calls these proxy methods and passes back the data retrieved from the server (or when the transfer is complete if it is a file download).
NSURLSession provides the status and Progress attributes, which are passed to the broker as additional information. It also supports cancel, resume, suspend, and resumable functions.
To master the use of NSURLSession, we need to know something about URL sessions
URL session
The behavior of tasks in a session depends on three aspects:
The type of session (as determined by the configuration object that created the session)
Types of tasks
Whether the application is in the foreground when the task is created
NSURLSession supports the following session types:
Default session: Behaves like other Foundation methods that download urls. Use disk-based caching and store certificates in the user keychain.
Ephemeral sessions: Do not store any data on disk; All caches, certificate stores, and so on are kept in RAM and tied to the session. This way, they are automatically released when the application terminates the session.
Background Sessions: Similar to the default session, except that a separate process handles all data transfers.
NSURLSession supports three task types within a session
Data tasks: Use NSData objects to send and receive data. Data tasks can return data in pieces, or they can return data all at once by completing the processor. Background sessions are not supported because data tasks do not store data to files.
Download task: receive data in the form of a file, support background download when the program is not running
Upload task: Usually send data in the form of a file, support background upload.
NSURLSession supports transferring data in the background while the application is suspended. Background transports are provided only by sessions created using background session configuration objects. When background sessions are used, the actual transmission is carried out in an independent process. Restarting the application process consumes resources and only a few features are available. Therefore, the following restrictions are imposed:
The session must provide a proxy for event distribution.
Only HTTP and HTTPS are supported
Only upload and download tasks are supported
Always accompany a redefinition operation
If the background transport is initialized when the application is in the background, the Discretionary property of the configured object is true
In iOS, when our application is no longer running, if the background download task is completed or a certificate is required, the system will automatically restart our application in the background. At the same time call UIApplicationDelegate object application: handlerEventsForBackgroundURLSession: completionHandler: method. This call provides the identity of the session that started the application. Our application should store completion handlers, use the same identity to create background configuration objects, and then use configuration objects to create sessions. The new session is associated with the running background activity. When the session background download task, will send the session agent a URLSessioinDidFinishEventsForBackgroundURLSession: message. Our proxy object then calls the stored completion handler.
Hang in a program to see if there are any task to complete, will call URLSession: downloadTask: didFinishDownloadingToURL: method. Likewise, if a task need certificate, NSURLSession object will invoke at the appropriate time URLSession: task: didReceiveChallenge: completionHandler: And URLSession: didReceiveChallenge: completionHandler: method.
The important thing to note here is that one session must be created for each identity, and the behavior of multiple sessions sharing the same identity is undefined.
Session and task objects implement the NSCopying protocol:
When an application copies a session or task object, it gets a pointer to the same object
When an application copies a configuration object, it gets a new object that can be modified separately
Create and configure NSURLSession
Let’s take a simple example of an NSURLSession interacting with the server.
Listing 1: Declare three types of session objects
@interface URLSession : NSObject
@property (nonatomic, strong) NSURLSession *backgroundSession;
@property (nonatomic, strong) NSURLSession *defaultSession;
@property (nonatomic, strong) NSURLSession *ephemeralSession;
@property (nonatomic, strong) NSMutableDictionary *completionHandlerDictionary;
– (void)addCompletionHandler:(CompletionHandlerType)handler forSession:(NSString *)identifier;
– (void)callCompletionHandlerForSession:(NSString *)identifier;
@end
NSURLSession provides a number of configuration options, including:
Support cache, cookie, authentication and protocol private storage
certification
Uploading and downloading files
Maximum number of configurations for each host
timeout
Minimum and minimum version of TLS supported
Custom proxy dictionary
Control cookie Policy
Controls HTTP pipe behavior
Since most of the Settings are contained in a separate configuration object, we can reuse these configurations. When we initialize a session object, we specify the following
A configuration object that manages the behavior of sessions and tasks within it
A proxy object that handles input data as it is received, and other events in the session and task, such as server authentication, determining whether a resource load request should be converted to download, and so on. This object is optional. But if we need to perform a background transport, we must provide a custom proxy.
After instantiating a session object, we cannot change the configuration or proxy.
Listing 2 shows how to create a session
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
// Configure session caching
NSString *cachePath = @”/MyCacheDirectory”;
NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [pathList objectAtIndex:0];
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSString *fullCachePath = [[path stringByAppendingPathComponent:bundleIdentifier] stringByAppendingPathComponent:cachePath];
NSLog(@”Cache path: %@”, fullCachePath);
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:16384 diskCapacity:268435456 diskPath:cachePath];
defaultConfigObject.URLCache = cache;
defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
self.defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
In addition to background configuration objects, we can reuse the configuration object of a session to create a new session. As mentioned above, copying a configuration object generates a new independent configuration object. We can safely modify configuration objects at any time. When a session is created, the session makes a deep copy of the configuration object, so changes only affect the new session. Proxy Listing 3 demonstrates creating a new session that uses a reused configuration object.
Listing 3: Reuse session objects
self.ephemeralSession = [NSURLSession sessionWithConfiguration:ephemeralConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
ephemeralConfigObject.allowsCellularAccess = YES;
// …
NSURLSession *ephemeralSessionWifiOnly = [NSURLSession sessionWithConfiguration:ephemeralConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
Retrieving data using NSURLSession is basically a two-step process:
Create a configuration object and a session based on that object
Define a request completion handler to process the acquired data.
If you use a system-provided agent, all you need is the lines in Listing 4
Listing 4: Using the system to provide the agent
NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
[delegateFreeSession dataTaskWithRequest:@”http://www.sina.com”
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@”Got response %@”, response);
}];
It is just that the proxy provided by the system provides limited network behavior. If the application requires more processing, such as custom authentication or background download, you need to use a custom proxy. When a custom agent is used to retrieve data, the agent must implement the following methods:
URLSession: dataTask: didReceiveData: from the request to provide data to our mission, a block of data at a time
URLSession: task: didCompleteWithError: it means the task has accepted all of the data.
If we’re in URLSession: dataTask: didReceiveData: method using data after return, you need to store the data in a certain place.
Listing 5: demonstrates a data access example:
NSURL *url = [NSURL URLWithString:@”http://www.sina.com”];
NSURLSessionDataTask *dataTask = [self.defaultSession dataTaskWithURL:url];
[dataTask resume];
If the status returned by the remote server indicates that an authentication is required and authentication requires connection-level processing, NSURLSession invokes the authentication-related proxy method. We will discuss this in detail later in the article.
Handle iOS background activities
With NSURLSession in iOS, our app is automatically launched when a download is complete. Application proxy method of application: handleEventsForBackgroundURLSession: completionHandler: Responsible for creating a proper conversation, storage request processor, and during the session call agent URLSessionDidFinishEventsForBackgroundURLSession: method is called when the processor. Listing 6 and Listing 7 illustrate this process
Listing 6: Session proxy method for iOS background download
– (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
NSLog(@”background url session %@”, session);
if (session.configuration.identifier)
{
[self callCompletionHandlerForSession:session.configuration.identifier];
}
}
– (void)callCompletionHandlerForSession:(NSString *)identifier
{
CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey:identifier];
if (handler) {
[self.completionHandlerDictionary removeObjectForKey:identifier];
handler();
}
}
Listing 7: App agent method for iOS background download
– (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
{
NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
URLSession *sessionDelegate = [[URLSession alloc] init];
NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfigObject
delegate:sessionDelegate
delegateQueue:[NSOperationQueue mainQueue]];
[sessionDelegate addCompletionHandler:completionHandler forSession:identifier];
}