1. An overview of the

NSURLSession comes after NSURLConnection to replace NSURLConnection for network requests. NSURLSession doesn’t just refer to the class itself, it actually refers to a list of related classes and protocols in the URL loading system of the Foundation framework, It is mainly composed of NSURLSessionConfiguration, NSURLSession and NSURLSessionTask the three class and its subclasses as well as the related agreement.

Including NSURLSessionConfiguration for configuration available network, cookies, security, caching policy, custom protocol, start events, such as options, used to initial NSURLSession object. NSURLSession is responsible for network requests and responses. NSURLSessionTask The NSURLSessionTask is used to create and execute tasks such as obtaining data, uploading data, and downloading data.

2. NSURLSessionConfiguration

2.1 the initialization

Initialized NSURLSessionConfiguration object used to NSURLSession. There are three NSURLSessionConfiguration initialization method.

2.1.1 the first
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
Copy the code

The config created in this way is a standard configuration with shared NSHTTPCookieStorage, shared NSURLCache, and shared NSURLCredentialStorage.

2.1.2 the second
NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration];
Copy the code

The Config created in this way does not persist caches, cookies, and certificates. When a session created in this way is released, or a memory warning is received, or the program exits, its cached information is cleared.

2.1.3 the third
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"abc"];
Copy the code

The Config created in this way is used to create a session that can be executed in the background when we need to continue uploading or downloading tasks in case the application hangs or exits. This way you create a config with a unique identifier that cannot be nil or an empty string. This identifier can be used to recover unfinished downloads or uploads when the program exits and restarts.

2.2 Attributes

2.2.1 Identifier (Unique Identifier)
@property (nullable, readonly, copy) NSString *identifier;
Copy the code

Identifier is read-only, only through backgroundSessionConfigurationWithIdentifier: this method to initialize the incoming, the label cannot be nil or an empty string, This flag can be used to restore unfinished download or upload tasks when the program is restarted after exit.

2.2.2 requestCachePolicy(CachePolicy)
@property NSURLRequestCachePolicy requestCachePolicy;
Copy the code

RequestCachePolicy is a caching policy and is an enumerated type, as follows:

Typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy) {// The default cache policy. If the cache does not exist, it is directly fetched from the server. The system determines the next operation according to the cache-Control field in response. For example, if the cache-Control field is must-Revalidata, the server is asked whether the data has been updated. If there is no update, the Cache data is directly returned to the user. NSURLRequestUseProtocolCachePolicy = 0, / / ignore the local cache data, Direct request to the server NSURLRequestReloadIgnoringLocalCacheData = 1, NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData, / / ignore the local cache, proxy servers, and other agencies, Directly request the source server NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, / / a Cache with it, regardless of its effectiveness (ignoring cache-control field), No request server NSURLRequestReturnCacheDataElseLoad = 2, / / only from the local cache loading, Local cache without operation (no Internet use) not NSURLRequestReturnCacheDataDontLoad = 3, / / cache the data must be confirmed the service side effective use NSURLRequestReloadRevalidatingCacheData = 5,};Copy the code
2.2.3 timeoutIntervalForRequest (request timeout)
@property NSTimeInterval timeoutIntervalForRequest;
Copy the code

Set the request timeout duration. The default value is 60 seconds.

2.2.4 timeoutIntervalForResource timeout (resources)
@property NSTimeInterval timeoutIntervalForResource;
Copy the code

Used to set the resource timeout period. The default is 7 days, which means that the resource must arrive within 7 days.

2.2.5 networkServiceType(Network Transfer type)
@property NSURLRequestNetworkServiceType networkServiceType;
Copy the code

Specify the network transport type, usually the default.

Typedef NS_ENUM (NSUInteger, NSURLRequestNetworkServiceType) {/ / the default value, Common network transmission NSURLNetworkServiceTypeDefault = 0, / / network voice communication transmission, Can only be used for voice over IP flow NSURLNetworkServiceTypeVoIP = 1, / / image transfer NSURLNetworkServiceTypeVideo = 2, / / network background transmission NSURLNetworkServiceTypeBackground = 3, / / voice transmission NSURLNetworkServiceTypeVoice = 4, / / specified request for responsive time sensitive data NSURLNetworkServiceTypeResponsiveData = 6, NSURLNetworkServiceTypeAVStreaming = 8, NSURLNetworkServiceTypeResponsiveAV = 9, NSURLNetworkServiceTypeCallSignaling = 11, };Copy the code
2.2.6 allowsCellularAccess(Cellular network or not)
@property BOOL allowsCellularAccess;
Copy the code

Specifies whether to use a cellular network. The default is YES. For example, when the user is watching a video without WiFi enabled, the user can be prompted to use data.

2.2.7 allowsExpensiveNetworkAccess (whether or not to use expensive network)
@property BOOL allowsExpensiveNetworkAccess;
Copy the code

This is a new feature in iOS 13, which literally means that the system automatically determines whether to use expensive networks when connected to cellular data or personal hotspots. (The default is YES).

2.2.8 allowsConstrainedNetworkAccess (whether or not to use restricted network)
@property BOOL allowsConstrainedNetworkAccess;
Copy the code

This is also a new feature in iOS 13, which literally means that users can set whether or not to use restricted networks when low traffic mode is enabled. (The default is YES).

2.2.9 waitsForConnectivity(Whether to wait for connection)
@property BOOL waitsForConnectivity;
Copy the code

This property is used to set whether to wait for the network connection to be available before executing the network request task. The default is NO. For example, I am only connected to the cellular network, but the user of the APP has set the property of waitsForConnectivity to YES, then the error of network connection failure will not be returned immediately when the request is initiated. But will wait for the network is available, such as connected to the WiFi) to perform network request, this case set timeoutIntervalForRequest is not effective, and timeoutIntervalForResource is effective.

2.2.10 discretionary
@property (getter=isDiscretionary) BOOL discretionary;
Copy the code

Used to determine whether background tasks can be scheduled for optimal performance based on the judgment of the system.

2.2.11 sharedContainerIdentifier
@property (nullable, copy) NSString *sharedContainerIdentifier;
Copy the code

If an application extension (what is an application extension?) Created NSURLSession tasks in the background, then you must set up a Shared container, to ensure that the application extension and carrier to realize data sharing, sharedContainerIdentifier is used to specify a Shared container, then we can get to the Shared container through the identifier.

2.2.12 sessionSendsLaunchEvents
@property BOOL sessionSendsLaunchEvents;
Copy the code

Used to set whether the application should continue or start in the background when the transfer is complete. Defaults to YES, and it is only through + backgroundSessionConfigurationWithIdentifier: create NSURLSessionConfiguration.

2.2.13 connectionProxyDictionary
@property (nullable, copy) NSDictionary *connectionProxyDictionary;
Copy the code

A dictionary containing information about the agents used in this session.

2.2.14 TLSMinimumSupportedProtocol
@property SSLProtocol TLSMinimumSupportedProtocol;
Copy the code

Request the lowest TLS version supported. The default is kSSLProtocol3, or SSL3.0.

2.2.15 TLSMaximumSupportedProtocol
Request the highest TLS version supported. The default is kTLSProtocol12, or TLS1.2. @property SSLProtocol TLSMaximumSupportedProtocol;Copy the code
2.2.16 HTTPShouldUsePipelining
@property BOOL HTTPShouldUsePipelining;
Copy the code

Used to enable HTTP pipelining, which can significantly reduce the load time of requests, but is not widely supported by servers and defaults to NO.

2.2.17 HTTPShouldSetCookies
@property BOOL HTTPShouldSetCookies;
Copy the code

Specifies whether the request should use the session-stored Cookie, the value of the HTTPCookieStorage property.

2.2.18 HTTPCookieAcceptPolicy
@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy; typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) { NSHTTPCookieAcceptPolicyAlways, / / to accept all cookies NSHTTPCookieAcceptPolicyNever, / / to refuse all cookies NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain / / only accept cookies from the main document domain};Copy the code

Determines when a Session should accept cookies sent from the server.

2.2.19 HTTPAdditionalHeaders
@property (nullable, copy) NSDictionary *HTTPAdditionalHeaders;
Copy the code

Is a dictionary that contains additional Reques headers that need to be added to the session, null by default. If the additional header field added to HTTPAdditionalHeaders is the same as that in NSURLRequest, the request header field in the NSURLRequest object is preferred.

NSURLSession already adds request header fields to NSURLRequest by default, Including Authorization, Connection, Host, proxy-authenticate, proxy-authorization, and www-authenticate.

HTTPAddtionalHeaders Additional request header fields you can add include Accept, Accept-language, user-Agent, and so on.

2.2.20 HTTPMaximumConnectionsPerHost
@property NSInteger HTTPMaximumConnectionsPerHost;
Copy the code

Specifies the maximum number of simultaneous connections to a host in a session.

2.2.21 HTTPCookieStorage
@property (nullable, retain) NSHTTPCookieStorage *HTTPCookieStorage;
Copy the code

Stores the cookies used by the session. Through defaultSessionConfiguration and backgroundSessionConfigurationWithIdentifier: create config will use NSHTTPCookieStorage + SharedHTTPCookieStorage singleton, to clear stored cookies, just set it to nil. Create the config through ephemeralSessionConfiguration ` ` cookie stored into memory, only the session invalidation automatically cleared.

2.2.22 URLCredentialStorage
@property (nullable, retain) NSURLCredentialStorage *URLCredentialStorage;
Copy the code

Certificate store. Through defaultSessionConfiguration and backgroundSessionConfigurationWithIdentifier: create config will use NSURLCredentialStorage + SharedCredentialStorage singleton, to clear the stored certificate, set to nil. Create the config certificate only through ephemeralSessionConfiguration stored into memory, the session invalidation automatically cleared.

2.2.23 URLCache
@property (nullable, retain) NSURLCache *URLCache;
Copy the code

Cache the response of NSURLRequest. The default configuration, the default is sharedURLCache, and the background configuration, the default is nil. If the configuration is temporary, the cache is stored in the memory. If the session expires, the cache is automatically cleared.

2.2.24 shouldUseExtendedBackgroundIdleMode
@property BOOL shouldUseExtendedBackgroundIdleMode;
Copy the code

Enable extended background idle mode for any TCP socket you create. Enabling this mode requires the system to remain on and delay reclaiming when the process moves into the background.

2.2.25 protocolClasses
@property(copy) NSArray<Class> *protocolClasses;
Copy the code

An array to configure the custom protocol (which is a subclass of NSURLProtocol) used for a particular session.

2.2.26 multipathServiceType
@property NSURLSessionMultipathServiceType multipathServiceType; typedef NS_ENUM(NSInteger, NSURLSessionMultipathServiceType) { NSURLSessionMultipathServiceTypeNone = 0, / / do not use the multipath TCP service NSURLSessionMultipathServiceTypeHandover = 1 (the default), / / multipath TCP services, to provide seamless switching between wi-fi and cellular, in order to keep the connection. NSURLSessionMultipathServiceTypeInteractive = 2, / / try to use the minimum delay interface service NSURLSessionMultipathServiceTypeAggregate = 3 / / aggregate other multipath option service capacity, to improve throughput and minimize delays. }Copy the code

Specifies the multipath TCP connection policy for transmitting data over Wi-Fi and cellular networks.

3. NSURLSession

We can use the NSURLSession API to create one or more session objects, each of which can manage multiple network request tasks. There are three ways to create a session:

3.1 Obtaining a Global Session

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

Get the global NSURLSession object in this way.

3.2 specify NSURLSessionConfiguration created the session

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
Copy the code

First create a config NSURLSessionConfiguration object, and then create the session according to the config.

3.3 Creating a Session with a Proxy

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

This way also need a NSURLSessionConfiguration object, and to follow NSURLSessionDelegate agreement.

4 NSURLSessionTask

NSURLSessionTask is an abstract class, it contains three subclasses: NSURLSessionDataTask, NSURLSessionUploadTask, NSURLSessionDownloadTask. Their inheritance relationship is as follows:

NSURLSessionTask can return data in two main ways: callback (completionHandler) and proxy. Any task is created based on the NSURLSession object. After the task is created, it must call [Task Resume] to start the task.

4.1 NSURLSessionDataTask

NSURLSessionDataTask inherits from NSURLSessionTask and is mainly used to read simple data on the server, such as JSON data. There are 4 ways to create NSURLSessionDataTask, which are respectively created based on NSURL and NSURLRequest objects. Each method is divided into two types: call back and call back.

    NSURL *url = [NSURL URLWithString:@"http://aaa.bbb/test/login"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLSession *session = [NSURLSession sharedSession]; Task NSURLSessionDataTask *task1 = [Session dataTaskWithURL:url]; / / the second: task based on NSURLRequest created not with callback NSURLSessionDataTask * task2 = [session dataTaskWithRequest: request]; // The third type: Task NSURLSessionDataTask *task3 = [session dataTaskWithURL: URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { }]; // Based on NSURLRequest create with callback task NSURLSessionDataTask * task4 = [session dataTaskWithRequest: request completionHandler: ^ (NSData *  _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { }]; // Task [task1 resume] is executed only if the task calls resume;Copy the code

4.2 NSURLSessionUploadTask

NSURLSessionUploadTask inherits from NSURLSessionDataTask and is mainly used to upload file data to the server. There are five ways to create a task.

// Upload through the file path (one callback and one non-callback). - (void)NSURLSessionUploadTask1{NSURL *fileUrl = [NSURL fileURLWithPath:@"/user/file/abc.txt"];
    
    NSURL *url = [NSURL URLWithString:@"http://aaa.bbb/test/upload"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    [request setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"]; NSURLSession *session = [NSURLSession sharedSession]; / / back to adjust NSURLSessionUploadTask not * task = [session uploadTaskWithRequest: request fromFile: fileUrl]; / / back to adjust NSURLSessionUploadTask * task = [session uploadTaskWithRequest: request fromFile: fileUrl completionHandler: ^ (NSData  * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { }]; [task resume]; }Copy the code
// Upload NSData. - (void)NSURLSessionUploadTask2{NSData *data = [NSData dataWithContentsOfFile:@"/user/file/abc.txt"];
    
    NSURL *url = [NSURL URLWithString:@"http://aaa.bbb/test/upload"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)data.length] forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"]; NSURLSession *session = [NSURLSession sharedSession]; / / back to adjust NSURLSessionUploadTask not * task = [session uploadTaskWithRequest: request fromData: data]; / / back to adjust NSURLSessionUploadTask * task = [session uploadTaskWithRequest: request fromData: data completionHandler: ^ (NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { }]; [task resume]; }Copy the code
- (void)NSURLSessionUploadTask3{NSURL * URL = [NSURL URLWithString:@"http://aaa.bbb/test/upload"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    request.HTTPBodyStream = [NSInputStream inputStreamWithFileAtPath:@"/user/file/abc.txt"];
    [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)data.length] forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
    
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionUploadTask *task = [session uploadTaskWithStreamedRequest:request];
    [task resume];
}
Copy the code

4.3 NSURLSessionDownloadTask

NSURLSessionDownloadTask inherits from NSURLSessionTask and is mainly used for file downloading. There are six ways to create a download task. Note that the file download saves a temporary file. After downloading the file, copy it to the directory you want to store it and then delete the temporary file.

- (void)NSURLSessionDownloadTaskTest{
    NSString *urlStr = @"http://aaa.bbb/test/downloadFile.zip"; NSURL *url = [NSURL URLWithString:urlStr]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; / / no need to download the background, you can use other ways to initialize the config NSURLSessionConfiguration * config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"abcd"]; NSURLSession *session = [NSURLSession sessionWithConfiguration:config]; NSURLSessionDownloadTask *task1 = [session downloadTaskWithURL:url]; NSURLSessionDownloadTask *task1 = [session downloadTaskWithURL:url]; // The second type, Create a task from an NSURL object. NSURLSessionDownloadTask *task2 = [session downloadTaskWithURL: URL completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { }]; / / the third, through an NSURLRequest object to create a task (not with callback) NSURLSessionDownloadTask * task3 = [session downloadTaskWithRequest: request]; // The fourth type, Through an NSURLRequest object to create a task (with callback) NSURLSessionDownloadTask * task4 = [session downloadTaskWithRequest: request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { }]; // The fifth type, NSString *resumePath = [NSTemporaryDirectory() to create task(without callback) from a resumeData(download progress saved in sandbox) data stringByAppendingPathComponent:@"123.tmp"]; NSData *resumeData = [NSData dataWithContentsOfFile:resumePath]; NSURLSessionDownloadTask *task5 = [session downloadTaskWithResumeData:resumeData]; // The sixth type, Through a resumeData data to create a task (with callback) NSURLSessionDownloadTask * task6 = [session downloadTaskWithResumeData: resumeData completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { }]; // Start task [task1 resume]; }Copy the code

ResumeData, which is generated when the download is paused, is passed through the callback to record the progress of the download. We want to save this data in the sandbox so that we can use this data to create the download task when the download continues (breakpoint continuation).

/ / pause download - (void) pauseDownload {[self. DownloadTask cancelByProducingResumeData: ^ (NSData * _Nullable resumeData) {/ / Record the downloaded data / / to save the download progress data in sandbox nsstrings * path = [NSTemporaryDirectory () stringByAppendingPathComponent: @"123.tmp"];
        [self.resumData writeToFile:path atomically:YES];
    }];
}
Copy the code

5. NSURLSessionDelegate

Relevant agents mainly has four: NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate. Their inheritance relationship is as follows:

5.1 NSURLSessionDelegate

NSURLSessionDelegate is used to handle session-level events, such as the lifetime of the session and server requests to verify the client’s identity or certificate.

5.1.1 Handling the Session life cycle

- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error;
Copy the code

This proxy method is called when a session expires, and there are two ways to invalidate a session.

  • - (void)finishTasksAndInvalidate;:sessionWill wait until alltaskCall this delegate method after completion or failure.
  • - (void)invalidateAndCancel;:sessionWill simply cancel all executingtaskImmediately invoke this delegate method.

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session;
Copy the code

If backgroundSessionConfigurationWithIdentifier:, by creating a configuration, and then through the configuration to create the session to manage can upload or download task is being executed in the background, The above proxy method is called when the background transfer is complete.

When the background transfer is complete, if the APP is not started at this point, the APP will automatically restart in the background, which will call the following proxy method in UIApplicationDelegate, which contains a session identifier and completionHandler, We will first save the completionHandler, then regenerate the Configuration according to the Identifier, and then the session created through this configuration will be re-associated with the corresponding background task.

// UIApplicationDelegate - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler;Copy the code
5.1.2 Handling Session Authentication

The following proxy method is invoked when the server requests a client certificate or requests validation of NTLM authentication, or when SSL or TLS is used to connect to the server.

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{/* Challenge is an object that encapsulates the authentication request sent by the server. Verify the client certificate NSURLAuthenticationMethodNegotiate NSURLAuthenticationMethodClientCertificate said required to use Kerberos or NTLM authentication NSURLAuthenticationMethodNTLM use NTLM authentication NSURLAuthenticationMethodServerTrust certificate provided by the authentication server * / nsstrings *authenticationMethod = [challenge.protectionSpace authenticationMethod]; /* The completionHandler callback passes two arguments: the first argument is an enumeration:  typedef NS_ENUM(NSInteger, NSURLSessionAuthChallengeDisposition) { NSURLSessionAuthChallengeUseCredential = 0, / / specified by another parameter the credential certificate NSURLSessionAuthChallengePerformDefaultHandling = 1, / / equivalent to not implement proxy approach, using the default way to handle it, Do not use the parameters of the credential NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, / / cancel the request, Provide credentials parameter is ignored NSURLSessionAuthChallengeRejectProtectionSpace = 3, / / reject the protectionSpace validation, do not use the parameters of the credential} the second argument: The second parameter is the NSURLCredential type, which is an authentication credential that contains credential type-specific information and a persistent storage type for use. When the first parameter is NSURLSessionAuthChallengeUseCredential, the second parameter must pass the authentication credential, or pass nil; Three types of credential can be created with NSURLCredential: 1. When authenticationMethod values for NSURLAuthenticationMethodHTTPBasic or NSURLAuthenticationMethodHTTPDigest, call the following method to create:  - (instancetype)initWithUser:(NSString *)user password:(NSString *)password persistence:(NSURLCredentialPersistence)persistence; + (NSURLCredential *)credentialWithUser:(NSString *)user password:(NSString *)password persistence:(NSURLCredentialPersistence)persistence; 2. When authenticationMethod value for NSURLAuthenticationMethodClientCertificate, call the following method to create:  - (instancetype)initWithIdentity:(SecIdentityRef)identity certificates:(nullable NSArray *)certArray persistence:(NSURLCredentialPersistence)persistence; + (NSURLCredential *)credentialWithIdentity:(SecIdentityRef)identity certificates:(nullable NSArray *)certArray persistence:(NSURLCredentialPersistence)persistence; 3. When authenticationMethod values for NSURLAuthenticationMethodServerTrust, call the following method to create:  - (instancetype)initWithTrust:(SecTrustRef)trust; + (NSURLCredential *)credentialForTrust:(SecTrustRef)trust; * /}Copy the code

If the above proxy method is not implemented, the following method of NSURLSessionTaskDelegate is called:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable Credential))completionHandler{/* There are several possibilities for authenticationMethod here NSURLAuthenticationMethodDefault default validation NSURLAuthenticationMethodHTMLForm not for URL Loading System, Through a web form validation can use NSURLAuthenticationMethodHTTPBasic basic HTTP authentication, through NSURLCredential object to provide user name and password, Equivalent to the Default Default validation NSURLAuthenticationMethodHTTPDigest basic HTTP authentication, similar to the automatically generated, Also through NSURLCredential object provides the user name and password * / nsstrings * authenticationMethod = [challenge. ProtectionSpace authenticationMethod]; }Copy the code

5.2 NSURLSessionTaskDelegate

NSURLSessionTaskDelegate Handles task-level events.

5.2.1 Handling the Task Life Cycle
- (void)URLSession:(NSURLSession *)session 
              task:(NSURLSessionTask *)task 
didCompleteWithError:(NSError *)error;
Copy the code

Return to this method when the task is complete. Note that error is only client-side errors, such as failing to resolve a host name or connect to a host. Server errors are not passed through this error.

5.2.2 Handling Task redirection
- (void)URLSession:(NSURLSession *)session 
              task:(NSURLSessionTask *)task 
willPerformHTTPRedirection:(NSHTTPURLResponse *)response 
        newRequest:(NSURLRequest *)request 
 completionHandler:(void (^)(NSURLRequest *))completionHandler;
Copy the code

This method is called when the server requests an HTTP redirect. Note this method is only applicable to defaultSessionConfiguration and ephemeralSessionConfiguration session to generate the session, BackgroundSessionConfigurationWithIdentifier: to generate the session will automatically redirect, and won’t go this way.

  • responseIs the server’s response to the original request
  • requestIs the newNSURLRequest
  • completionHandlerCallbacks can pass a redirectNSURLRequestObject, you can also pass nil, if you pass nil, you don’t redirect.
5.2.3 Handling Task Uploading
- (void)URLSession:(NSURLSession *)session 
              task:(NSURLSessionTask *)task 
   didSendBodyData:(int64_t)bytesSent 
    totalBytesSent:(int64_t)totalBytesSent 
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;
Copy the code

This proxy method is called periodically to inform upload progress when an upload task is executed.

  • bytesSentThe number of bytes sent between the last call to the method and this call.
  • totalBytesSentIs the total number of bytes sent.
  • totalBytesExpectedToSendIs the total length of data to be uploaded.

- (void)URLSession:(NSURLSession *)session 
              task:(NSURLSessionTask *)task 
 needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler;
Copy the code

When we pass uploadTaskWithStreamedRequest: this method to create the task, must realize this proxy approach, when this method is called, need through the completionHandler callback incoming NSInputStream object. Because the upload may fail, this proxy method is called when it fails, and the request body flow needs to be resupplied in this method.

5.2.4 Handling identity authentication
- (void)URLSession:(NSURLSession *)session 
              task:(NSURLSessionTask *)task 
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge 
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;
Copy the code

This proxy method is used to handle task-level authentication. If the session-level authentication proxy function is not implemented, this proxy will be invoked.

5.2.5 Handling delayed and waiting Tasks
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willBeginDelayedRequest:(NSURLRequest *)request  completionHandler:(void (^)(NSURLSessionDelayedRequestDisposition disposition, NSURLRequest *newRequest))completionHandler; Typedefs NS_ENUM(NSInteger, NSURLSessionDelayedRequestDisposition) { NSURLSessionDelayedRequestContinueLoading = 0, / / stick with the original request NSURLSessionDelayedRequestUseNewRequest = 1, using a new request execution / / download NSURLSessionDelayedRequestCancel = 2, / / cancel the task}Copy the code

This proxy method is called when a latency start task, such as the property set, is ready to be written. You only need to implement this delegate method if you are waiting for the network to load and need to be replaced by a new request.

The completionHandler callback tells the Task what to do. When the disposition is NSURLSessionDelayedRequestUseNewRequest need to preach a new NSURLRequest object at the same time.


- (void)URLSession:(NSURLSession *)session 
taskIsWaitingForConnectivity:(NSURLSessionTask *)task;
Copy the code

When NSURLSessionConfiguration waitsForConnectivity attribute is set to YES and can’t get enough connectivity will call the agent method. For example, the current user is only connected to the cellular network, but the user can only watch the video when the WiFi connection is set. When the user plays the video, this proxy method will be called. Then we can update the UI in this proxy method to remind the user to connect to WiFi. Note that this method is called at most once per task and only when the connection is initially unavailable.

5.2.6 Execution Of a Collection Task
- (void)URLSession:(NSURLSession *)session 
              task:(NSURLSessionTask *)task 
didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics;
Copy the code

After a task is executed, you can use this method to know the task execution status, such as task execution duration, redirection times and other information in the NSURLSessionTaskMetrics object.

5.3 NSURLSessionDataDelegate

NSURLSessionDataDelegate inherits from NSURLSessionTaskDelegate and is used to handle dataTask data (response received, data received, whether to cache data, etc.).

5.3.1 Handling the Task Life Cycle
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler; / / disposition of enumerated types typedef NS_ENUM (NSInteger NSURLSessionResponseDisposition) {NSURLSessionResponseCancel = 0, / / the task will be cancelled NSURLSessionResponseAllow = 1, / / the task normally NSURLSessionResponseBecomeDownload = 2, / / into a downloadTask NSURLSessionResponseBecomeStream / / into a StreamTask}Copy the code

This proxy method is invoked when the DataTask receives the response. We need to specify how the task will proceed through the completionHandler callback.

  • When the incomingdispositionforNSURLSessionResponseBecomeDownloadIt, will betaskconvertdownload task, will also callURLSession:dataTask:didBecomeDownloadTask:This proxy method.
  • When the incomingdispositionforNSURLSessionResponseBecomeStreamIt, will betaskconvertStreamTask, will also callURLSession:dataTask:didBecomeStreamTask:This proxy method.

When the content-type of our request supports multipart/ X-mixed-replace, the server will fragment the data back, and each time the data back overwrites the previous data. This method is called every time new data is returned, and we should properly process the previous data in this function, otherwise it will be overwritten by the new data. If we do not provide an implementation of this method, the session will continue the task, that is, overwrite the previous data.


- (void)URLSession:(NSURLSession *)session 
          dataTask:(NSURLSessionDataTask *)dataTask 
didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask;
Copy the code

When this proxy method is called has been described above.


- (void)URLSession:(NSURLSession *)session 
          dataTask:(NSURLSessionDataTask *)dataTask 
didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask;
Copy the code

When this proxy method is called has been described above.

5.3.2 Receiving Data
- (void)URLSession:(NSURLSession *)session 
          dataTask:(NSURLSessionDataTask *)dataTask 
    didReceiveData:(NSData *)data;
Copy the code

This proxy method is called when we receive data, and it is called many times, and we need to concatenate each received data to get the complete data.

5.3.3 Handling caching
- (void)URLSession:(NSURLSession *)session 
          dataTask:(NSURLSessionDataTask *)dataTask 
 willCacheResponse:(NSCachedURLResponse *)proposedResponse 
 completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler;
Copy the code

The session calls this proxy method when the Task has received all the expected data. If this method is not implemented, the caching policy of the Configuration object used when the session was created is used.

5.4 NSURLSessionDownloadDelegate

NSURLSessionDownloadDelegate inherited from NSURLSessionTaskDelegate, mainly used to handle downloads.

5.4.1 Handling the Lifecycle of a Download Task
- (void)URLSession:(NSURLSession *)session 
      downloadTask:(NSURLSessionDownloadTask *)downloadTask 
didFinishDownloadingToURL:(NSURL *)location;
Copy the code

This proxy method is called when the download task is complete and must be implemented. Location is the location where the downloaded file is saved. Note that we must save the downloaded file to the desired directory in this method, because this method returns a temporary path and the file in this path will be deleted after this method ends. In addition, if the content of the file is read, it needs to be executed in the child thread, otherwise the page may freeze.

5.4.2 Resuming downloads
- (void)URLSession:(NSURLSession *)session 
      downloadTask:(NSURLSessionDownloadTask *)downloadTask 
 didResumeAtOffset:(int64_t)fileOffset 
expectedTotalBytes:(int64_t)expectedTotalBytes;
Copy the code

This proxy method is called when a download is cancelled or resumes after a download failure. Note the fileOffset parameter, which is 0 if the file caching policy or the last update date of the file prevents the reuse of downloaded file content. Otherwise, this value represents the offset of data that has already been downloaded, and the download will start from that offset and will not be redownloaded.

Resume download through downloadTaskWithResumeData: this method to create a task, where did he get from the resumeData? As mentioned earlier, when the user manually cancels the download, the returned resumeData can be stored in the sandbox and retrieved from the sandbox when the download resumes.

Let’s look at another case where -urlSession: task is called when the download fails: DidCompleteWithError: This proxy method, which has resumeData in its error message, From the error of the UserInfo dictionary by NSURLSessionDownloadTaskResumeData the key to obtain resumeData.

5.4.3 Receiving progress updates
- (void)URLSession:(NSURLSession *)session 
      downloadTask:(NSURLSessionDownloadTask *)downloadTask 
      didWriteData:(int64_t)bytesWritten 
 totalBytesWritten:(int64_t)totalBytesWritten 
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
Copy the code

This proxy method is invoked periodically during the execution of the download task to notify the download progress.

  • bytesWrittenRepresents the number of bytes of data received between the last call to the method and this call.
  • totalBytesWrittenRepresents the total number of bytes received.
  • totalBytesExpectedToWriteRepresents the total length of data to be downloaded.