Detailed explanation of NSURLSession use of IOS network request

  • 2021-11-13 02:54:57
  • OfStack

Foreword:

Neither Android nor ios can be separated from interacting with the server, This must use network requests, I remember the ASIHTTPRequest framework used when I made iOS in 2013. Now, when iOS was picked up again, ASIHTTPRequest has stopped maintenance, and everyone is using AFNetWorking as the preferred network request framework. The previous ASIHTTPRequest was implemented based on NSURLConnection class, and the early AFNetWorking was also implemented based on NSURLConnection. Later, NSURLConnection was abandoned after iOS9, and NSURLSession introduced after iOS 7 was used. Based on the principle of tracing back to the source, first learn the implementation of NSURLSession.

Understanding NSURLSession

NSURLSession was released by iOS 7 in 2013 to replace NSURLConnection, and NSURLConnection was completely launched on the historical stage after iOS 9. It is very convenient to use, Today, get, post, form submission, file upload, file download, I, a silk programmer who mainly develops Android, am amazed. I can create a request Task according to the NSURLSession session object, and then execute the Task, including cache, session cycle and multithreaded task iOS, which have been encapsulated at the sdk level. Unfortunately, NSURLSession only provides asynchronous request mode but not synchronous request mode. Next, let's talk about how to realize the network request.

NSURLSession use

Let's start with a simple get request as an example.

1.) First construct an NSURL request resource address


  //  Structure URL Resource address 
  NSURL *url = [NSURL URLWithString:@http://api.nohttp.net/method?name=yanzhenjie&pwd=123];

2.) Create an NSRequest request object


  //  Create Request Request 
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  //  Configure Request Request 
  //  Set the request method 
  [request setHTTPMethod:@"GET"];
  //  Set request timeout   Default timeout 60s
  [request setTimeoutInterval:10.0];
  //  Setting header parameters 
  [request addValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
  // Or in the following way   Add all request headers 
  request.allHTTPHeaderFields=@{@"Content-Encoding":@"gzip"};
  // Setting Cache Policy 
  [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

Add unused settings according to requirements, such as request mode, timeout time and request header information. Here, the cache strategy is mainly introduced:

NSURLRequestUseProtocolCachePolicy = 0//Default cache policy, if the cache does not exist, get it directly from the server. If the cache exists, the next step operation will be judged according to the Cache-Control field in response. For example, if the Cache-Control field is must-revalidata, ask the server whether the data is updated. If there is no update, it will be directly returned to the user to cache the data. If it has been updated, request the server. NSURLRequestReloadIgnoringLocalCacheData = 1//Ignore the locally cached data and request the server directly. NSURLRequestIgnoringLocalAndRemoteCacheData = 4//Ignore the local cache, proxy server, and other intermediaries and request the source server directly. NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData NSURLRequestReturnCacheDataElseLoad = 2//Use the cache if it is available, regardless of its validity (i.e. ignore the Cache-Control fields), and request the server if it is not. NSURLRequestReturnCacheDataDontLoad = 3//Load local cache only. Failure if not. (Use when making sure there is no network currently) NSURLRequestReloadRevalidatingCacheData = 5//Cached data must be validated by the server before it can be used

3.) Create an NSURLSession session object

You can share Session with iOS


  //  Adopt the sharing provided by Apple session
  NSURLSession *sharedSession = [NSURLSession sharedSession];

You can configure different NSURLSession by NSURLSessionConfiguration


  //  Structure NSURLSessionConfiguration
  NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  //  Structure NSURLSession Network session; 
  NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

Three ways to create NSURLSession are provided through NSURLSessionConfiguration

defaultSessionConfiguration//The default configuration uses a persistent hard disk cache that stores certificates to the user's key chain. Stores cookie to shareCookie. ephemeralSessionConfiguration//Do not use permanent cookie, certificate, cache configuration, optimum data transfer. backgroundSessionConfigurationWithIdentifier//You can upload and download background tasks of HTTP and HTTPS (the program runs in the background).

In the background, the network transmission is handed over to a separate process of the system, and even if app hangs, pushes or even crashes, it will still be executed in the background.

You can also set timeout time and request first-class information through NSURLSessionConfiguration System 1


  //  Structure NSURLSessionConfiguration
  NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  // Set the request timeout to 10 Seconds 
  configuration.timeoutIntervalForRequest = 10;
  
  // Whether to continue the request (upload or download) in the case of cellular network 
  configuration.allowsCellularAccess = NO;

  // Configure the request header 
  configuration.HTTPAdditionalHeaders =@{@"Content-Encoding":@"gzip"};

4.) Create an NSURLSessionTask object and execute the


  //  Structure NSURLSessionTask Session tasks; 
  NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    //  Request failed, print error message 
    if (error) {
      NSLog(@"get error :%@",error.localizedDescription);
    }
    // Request successful, parsing data 
    else {
      // JSON Data format analysis 
      id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
      //  Determine whether the parsing is successful 
      if (error) {
        NSLog(@"get error :%@",error.localizedDescription);
      }else {
        NSLog(@"get success :%@",object);
        //  Parse successfully, process the data, and pass GCD Gets the main queue and refreshes the interface in the main thread. 
        dispatch_async(dispatch_get_main_queue(), ^{
          //  Refresh interface ....
        });
      }
    }
  }];

iOS provides different types of NSSessionTask for different application scenarios

NSURLSessionDataTask//1-like get, post, and so on NSURLSessionUploadTask//Used for uploading files or requests with large data volume NSURLSessionDownloadTask//Used for downloading files or requests with large data volume NSURLSessionStreamTask//Establish a hostname and port for an TCP/IP connection or a network service object.

Three Functions of task

-(void) suspend; //Pause -(void) resume; //Start or resume -(void) cancel; //Close the task

NSURLSession Additional Request Example

1.) post request


  // 1 , creating URL Resource address 
  NSURL *url = [NSURL URLWithString:@"http://api.nohttp.net/postBody"];
  // 2 , creating Reuest Request 
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  // 3 , configure Request
  //  Set request timeout 
  [request setTimeoutInterval:10.0];
  //  Set the request method 
  [request setHTTPMethod:@"POST"];
  //  Setting header parameters 
  [request addValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
  // 4 Constructing request parameters 
  // 4.1 Create dictionary parameters and put the parameters into the dictionary, which can prevent programmers from making mistakes subjectively, that is, making mistakes in parameter writing. 
  NSDictionary *parametersDict = @{@"name":@"yanzhenjie",@"pwd":@"123"};
  // 4.2 , traverse the dictionary to " key=value& "Creates a parameter string. 
  NSMutableString *parameterString = [[NSMutableString alloc]init];
  int pos =0;
  for (NSString *key in parametersDict.allKeys) {
    //  Splice string 
    [parameterString appendFormat:@"%@=%@", key, parametersDict[key]];
    if(pos<parametersDict.allKeys.count-1){
      [parameterString appendString:@"&"];
    }
    pos++;
  }
  // 4.3 , NSString Turn into NSData Data type. 
  NSData *parametersData = [parameterString dataUsingEncoding:NSUTF8StringEncoding];
  // 5 Set the request message 
  [request setHTTPBody:parametersData];
  // 6 , structure NSURLSessionConfiguration
  NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  // 7 Create a network session 
  NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
  // 8 Create a session task 
  NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    // 10 To determine whether the request was successful 
    if (error) {
      NSLog(@"post error :%@",error.localizedDescription);
    }else {
      //  If the request is successful, the data is parsed. 
      id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
      // 11 To determine whether the parsing is successful 
      if (error) {
        NSLog(@"post error :%@",error.localizedDescription);
      }else {
        //  Parse successfully, process the data, and pass GCD Gets the main queue and refreshes the interface in the main thread. 
        NSLog(@"post success :%@",object);
        dispatch_async(dispatch_get_main_queue(), ^{
          //  Refresh interface ...
        });
      }
    }
    
  }];
  // 9 , perform tasks 
  [task resume];

2.) Upload with form parameter file


  NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
  NSTimeInterval a=[dat timeIntervalSince1970];
  NSString* fileName = [NSString stringWithFormat:@"file_%0.f.txt", a];
  
  [FileUtils writeDataToFile:fileName data:[@"upload_file_to_server" dataUsingEncoding:NSUTF8StringEncoding]];
  
  //  Upload in the form of stream, the size is not limited in theory, but attention should be paid to the time 
  // 1 , creating URL Resource address 
  NSURL *url = [NSURL URLWithString:@"http://api.nohttp.net/upload"];
  // 2 , creating Reuest Request 
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  // 3 , configure Request
  // Settings Body Value method 2 This method is primitive and not commonly used, but it can be used to upload parameters and files 
  NSString *BOUNDARY = @"whoislcj";// Form boundary   You can customize any value 
  [request setValue:[@"multipart/form-data; boundary=" stringByAppendingString:BOUNDARY] forHTTPHeaderField:@"Content-Type"];
  //  Used for file upload post
  [request setHTTPMethod:@"POST"];
  //  Set request timeout 
  [request setTimeoutInterval:30.0f];
  // For storage 2 Binary data stream 
  NSMutableData *body = [NSMutableData data];
  
  // Append 1 Common form parameters  name=yanzhenjie
  NSString *nameParam = [NSString stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n",BOUNDARY,@"name",@"yanzhenjie",nil];
  [body appendData:[nameParam dataUsingEncoding:NSUTF8StringEncoding]];
  
  // Append 1 Common form parameters  pwd=123
  NSString *pwdParam = [NSString stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n",BOUNDARY,@"pwd",@"123",nil];
  [body appendData:[pwdParam dataUsingEncoding:NSUTF8StringEncoding]];
  
  // Append 1 File form parameters 
  // Content-Disposition: form-data; name="< Names that the server needs to know >"; filename="< The file name passed up on the server side >"
  // Content-Type: application/octet-stream -- Choose different values according to different file types 
  NSString *file = [NSString stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\";filename=\"%@\"\r\nContent-Type: application/octet-stream\r\n\r\n",BOUNDARY,@"headUrl",fileName,nil];
  [body appendData:[file dataUsingEncoding:NSUTF8StringEncoding]];
  // Get file Path 
  NSString *filePath =[FileUtils getFilePath:fileName];
  NSData *data =[NSData dataWithContentsOfFile:filePath];
  // Append a file 2 Binary data 
  [body appendData:data];
  [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
  // End dividing line 
  NSString *endString = [NSString stringWithFormat:@"--%@--",BOUNDARY];
  [body appendData:[endString dataUsingEncoding:NSUTF8StringEncoding]];
  
  //  Create a session 
  NSURLSession *session = [NSURLSession sharedSession];
  // 3. Start uploading   request Adj. body data Will be ignored, and the fromData Provide 
  NSURLSessionUploadTask *uploadTask= [session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (error) {
      NSLog(@"upload error:%@",error);
    } else {
      NSLog(@"upload success : %@", [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error]);
      dispatch_async(dispatch_get_main_queue(), ^{
        //  Refresh interface ...
      });
    }
  }];
  // Perform a task 
  [uploadTask resume];

3.) File download


//  Create url
  NSString *urlStr =@"http://images2015.cnblogs.com/blog/950883/201701/950883-20170105104233581-62069155.png";
  NSURL *Url = [NSURL URLWithString:urlStr];
  //  Create a request 
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:Url];
  //  Set request timeout 
  [request setTimeoutInterval:30.0];
  //  Create a session 
  NSURLSession *session = [NSURLSession sharedSession];
  
  NSURLSessionDownloadTask *downLoadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (!error) {
      NSLog(@"download sucess : %@", location);
      NSData *data=[NSData dataWithContentsOfURL:location];
      UIImage *image=[UIImage imageWithData:data];
      dispatch_async(dispatch_get_main_queue(), ^{
        //  Refresh interface ...
        UIImageView *imageView =[[UIImageView alloc]init];
        imageView.image=image;
        [self.view addSubview:imageView];
        [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
          make.center.equalTo(self.view);
          make.size.mas_equalTo(CGSizeMake(300, 300));
        }];
      });
    } else {
      NSLog(@"download error : %@", error.localizedDescription);
    }
  }];
  // Start a task 
  [downLoadTask resume];

Summary:


Related articles: