An overview,

NSURLSession was introduced in 2013 with the release of iOS7, and apple positioned it as a replacement for NSURLConnection, and then gradually retired NSURLConnection. The most widely used third-party networking frameworks: AFNetworking, SDWebImage, and so on all use NSURLSession.

Session translated into Chinese means Session. As we know, in the seven-layer network protocol, there are physical layer -> data link layer -> network layer -> transmission layer -> Session layer -> presentation layer -> application layer. Then we can understand the NSURLSession class as Session layer, which is used to manage the creation, maintenance, deletion and other work of network interface. All we need to do is the layer after the session layer, and NSURLSession already encapsulates the low-level work for us.

In WWDC 2013, Apple’s team refacedNSURlConnection and introduced NSURLSession as a replacement. NSURLSession NSURLConnection to replace with NSURLSession and NSURLSessionConfiguration and three NSURLSessionTask subclass: NSURLSessionDataTask, NSURLSessionUploadTask, and NSURLSessionDownloadTask.

The relationship between them is shown below:

 

NSURLSessionTask and three subclasses:

 

NSURLSessionDataTask: Mainly used to read simple data from the server, such as JSON data.

NSURLSessionDownloadTask: the main purpose of this task is to download file, it aimed at a large file network request made more processing, such as download schedule, breakpoint continuingly, etc.

NSURLSessionUploadTask: Corresponding to the download task, this task is mainly used to send file data to the server.

 

Use of NSURLSession

NSURLSession itself does not make requests. Instead, it makes network requests in the form of creating tasks (calls to the resume() method). The same NSURLSession can create multiple tasks. The cache and cookies are shared between these tasks. There are several steps to using NSURLSession:

  • Step 1: Create the NSURLSession object
  • Step 2: Create a Task using the NSURLSession object
  • Step 3: Start the task

 

Create an NSURLSession object

There are three ways to create an NSURLSession object:

(1) Create it directly

NSURLSession *session = [NSURLSession sharedSession];Copy the code

(2) Create a vm after the configuration

[NSURLSession sessionWithConfiguration:defaultSessionConfiguration];Copy the code

(3) setting plus proxy gain

NSURLSession *session = [NSURLSession *session = [NSURLSession *session = [NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];Copy the code

There are three types of NSURLSession configuration:

/ / the default configuration will be stored on disk cache + (NSURLSessionConfiguration *) defaultSessionConfiguration; / / instantaneous session model does not create persistent storage cache + (NSURLSessionConfiguration *) ephemeralSessionConfiguration; / / background session mode allows program uploads and downloads in the background to work + backgroundSessionConfigurationWithIdentifier: (nsstrings NSURLSessionConfiguration (*) *)identifierCopy the code

 

Create a Task using the NSURLSession object

NSURLSessionTask Creation You need to create tasks based on specific requirements.

(1) NSURLSessionDataTask

Created from the Request object or URL:

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;

- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;Copy the code

 

Created from a request object or URL, specifying a block of code to be called back to via completionHandler when the task is completed:

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;    

- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;Copy the code

(2) NSURLSessionUploadTask

Created from request to specify the file source or data source at upload time:

- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;  
   
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;  
  
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;  Copy the code

 

Specify the block of code to call back after the task is completed via completionHandler:

- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;    

- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;Copy the code

(3) the NSURLSessionDownloadTask

Download tasks support breakpoint continuation, and the third way is to create a download task from previously downloaded data:

- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;    
    
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;    
  
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;Copy the code

Similarly, the completionHandler can specify a block of code to call back after the task is completed:

- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;    

- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;    

- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;Copy the code

We can specify the corresponding agent when using any of the three tasks. The proxy object structure of NSURLSession is as follows:

NSURLSessionDelegate – As the base class for all proxies, defines the most basic proxy method for network requests.

NSURLSessionTaskDelegate – Defines proxy methods related to network request tasks.

NSURLSessionDownloadDelegate – related proxy method is used to download task, such as download progress and so on.

NSURLSessionDataDelegate – Used for normal data tasks and upload tasks.

I believe everyone can use proxy, the specific use method is not explained here.

 

3. Start the task

// Start task [task resume];Copy the code

GET request and POST request

We can use NSURLSessionDataTask for GET and POST requests.

1. GET requests

NSURLSession * Session = [NSURLSession sharedSession]; NSURL *url = [NSURL URLWithString:@"http://www.xxx.com/login?username=myName&pwd=myPsd"]; NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); //NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);}]; //3, execute task resume;Copy the code

2. POST request

NSURLSession * Session = [NSURLSession sharedSession]; NSURL *url = [NSURL URLWithString:@"http://www.xxx.com/login"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST"; request.HTTPBody = [@"username=myName&pwd=myPsd" dataUsingEncoding:NSUTF8StringEncoding]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); //NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);}]; //3, execute task resume;Copy the code

4. Upload files

We can use NSURLSessionUploadTask to upload a file. There are two methods for uploading a file:

Method 1:

NSURLSessionUploadTask *task =
[[NSURLSession sharedSession] uploadTaskWithRequest:request
                                           fromFile:fileName
                                  completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];Copy the code

Method 2:

[self.session uploadTaskWithRequest:request
                            fromData:body
                   completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
 NSLog(@"-------%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
 }];Copy the code

1. Upload data streams

This method has the advantage of unlimited size. Example code is as follows:

- (void) NSURLSessionBinaryUploadTaskTest { // 1. Create a url nsstrings * urlString = @ "http://www.xxxx.com/upload.php"; // urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]; NSURL *url = [NSURL URLWithString:urlString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // Upload files using post request.HTTPMethod = @" post "; // 3. The body data that started uploading the request will be ignored. Which is provided by fromData [[[NSURLSession sharedSession] uploadTaskWithRequest: request fromData: [NSData dataWithContentsOfFile:@"/Users/lifengfeng/Desktop/test.jpg"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (error == nil) {NSLog(@"upload success: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); } else { NSLog(@"upload error:%@",error);  } }] resume]; }Copy the code

2. Upload in the form of splicing

  • The key to uploading is to concatenate the form in the request body and get the MIME Types of the local uploaded file. The actual network upload is simple. There is also a size limit to the way you concatenate a form, which is HTMLMAX_FILE_SIZELimit (can be set yourself, generally 2MB).
  • From the inheritance diagram above, we know that uploadTask is a subclass of dataTask and can be used instead of dataTask.

The form splicing format is as follows, boundary as the dividing line:

--boundary Content-Disposition:form-data; Name = "Form control name"; Filename = "Name of the uploaded file" content-type: specifies the file to be uploaded. MIME Types Specifies the binary data to be uploaded. --boundary--Copy the code

Example code is as follows:

- (void)NSURLSessionUploadTaskTest { // 1. Create a url using the Apache server local nsstrings * urlString = @ "http://localhost/upload/upload.php"; urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]; NSURL *url = [NSURL URLWithString:urlString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // Upload files using post request.HTTPMethod = @" post "; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",@"boundary"]; [request setValue:contentType forHTTPHeaderField:@"Content-Type"]; MAX_FILE_SIZE (2MB) FilePath: local FilePath to upload formName: form control name, Should be consistent in the server NSData * data = [self getHttpBodyWithFilePath: @ "/ Users/lifengfeng/Desktop/test. JPG" formName: @ "file" reName:@"newName.png"]; request.HTTPBody = data; // Whether to provide as required, not required, if not provided, [REQUEST setValue:[NSString stringWithFormat:@"%lu",data.length] forHTTPHeaderField:@"Content-Length"]; / / 4.1 use dataTask [[[NSURLSession sharedSession] dataTaskWithRequest: request completionHandler: ^ (NSData * _Nullable Data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (error == nil) {NSLog(@"upload success: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); } else { NSLog(@"upload error:%@",error);  } }] resume]; UploadTask fromData: Will be ignored [[[NSURLSession sharedSession] uploadTaskWithRequest: request fromData: nil completionHandler: ^ (NSData * _Nullable Data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (error == nil) {NSLog(@"upload success: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); } else { NSLog(@"upload error:%@",error);  } }] resume]; #endif }Copy the code

Two custom methods are used:

/// filePath: indicates the filePath to upload. FormName: indicates the form control name. File name after uploading - (NSData *)getHttpBodyWithFilePath:(NSString *)filePath formName:(NSString *)formName reName:(NSString *)reName { NSMutableData *data = [NSMutableData data]; NSURLResponse *response = [self getLocalFileResponse:filePath]; // fileType: MIMEType file size: expectedContentLength file name: suggestedFilename NSString *fileType = response.mimetype; // If no uploaded file name is passed in, use the local file name! if (reName == nil) { reName = response.suggestedFilename; } // form splitter NSMutableString *headerStrM =[NSMutableString string]; [headerStrM appendFormat:@"--%@\r\n",@"boundary"]; // name: form control name filename: upload filename [headerStrM appendFormat:@" content-disposition: form-data; name=%@; filename=%@\r\n",formName,reName]; [headerStrM appendFormat:@"Content-Type: %@\r\n\r\n",fileType]; [data appendData:[headerStrM dataUsingEncoding:NSUTF8StringEncoding]]; / / the file content NSData * fileData = [NSData dataWithContentsOfFile: filePath]; [data appendData:fileData]; NSMutableString *footerStrM = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",@"boundary"]; [data appendData:[footerStrM dataUsingEncoding:NSUTF8StringEncoding]]; // NSLog(@"dataStr=%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); return data; } // get the response, - (NSURLResponse *)getLocalFileResponse:(NSString *)urlString {urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]; / / local file request NSURL * url = [NSURL fileURLWithPath: urlString); NSURLRequest *request = [NSURLRequest requestWithURL:url]; __block NSURLResponse *localResponse = nil; // Dispatch_semaphoRE_t semaphore = dispatch_semaphore_create(0); [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { localResponse = response;  dispatch_semaphore_signal(semaphore); }] resume]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return localResponse; }Copy the code

Five, the download of files

We can use NSURLSessionDownloadTask to download the file. NSURLSession can also implement large file downloads using the proxy method, but it does not implement breakpoint downloads, so it is generally not used.

- (void)NSURLSessionDownloadTaskTest { // 1. Create url nsstrings * urlString = [nsstrings stringWithFormat: @ "http://www.xxx.com/test.mp3"); / / some special character encoding urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters: [NSCharacterSet URLQueryAllowedCharacterSet]]; NSURL *url = [NSURL URLWithString:urlString]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLSession *sharedSession = [NSURLSession sharedSession]; / / 4. Create a task NSURLSessionDownloadTask * downloadTask = [sharedSession downloadTaskWithRequest: request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (error == nil) {// location: location where files are stored after downloading. // It will only be saved temporarily, so you need to save it to NSLog(@"location:%@",location.path); // Use the simulator test, In order to convenient to download it to Mac desktop / / nsstrings * filePath = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory NSUserDomainMask, YES) lastObject]; NSString *filePath = @"/Users/lifengfeng/Desktop/test.mp3"; NSError *fileError;  [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:filePath error:&fileError];  if (fileError == nil) { NSLog(@"file save success"); } else { NSLog(@"file save error: %@",fileError); } } else { NSLog(@"download error:%@",error); } }]; Start the task [downloadTask Resume]. }Copy the code

The above is about the usage of NSURLSession, and the related proxy method is not explained. Through proxy method, we can achieve the acquisition of download progress, etc., specific according to the need to achieve their own.

Original article, reproduced please specify: reproduced from Li Fengfeng’s blog

This article link address: iOS NSURLSession details