前面一篇我们说了什么?


 

      这是这个关于NSURLSession的第二篇文章,第一篇再加上这篇文章,就大概的把NSURLSession的API以及一些简单使用我们也就说的差不多了,这篇文章总结哪些点呢?相信看顾哦第一篇文章的小伙伴都知道,在开始写这篇文章之前我们说说上一篇文章我们写了些什么。

      1、NSURLRequest

      2、NSURLSession

      3、NSURLSessionTask 以及它的三个子类:NSURLSessionDataTask/NSURLSessionDownloadTask/NSURLSessionStreamTask

     

      第一篇文章的飞机票在这里 NSURLSession 所有的都在这里(一)

 

      拿着一篇我们说的大概是下面这些内容了:

      1、NSURLSessionTaskDelegate

      2、NSURLSessionDataDelegate

      3、NSURLSessionDownloadDelegate

      4、NSURLSessionStreamDelegate

      5、NSURLSessionTaskTransactionMetrics

      6、NSURLSessionTaskMetrics

 

开始这篇的内容  — delegate


      在说明之前我们先通过一张图看看这几个代理之间的关系:

      这些代理全都是遵循了NSURLSessionDelegate,再说上面我们提到的那些代理的API之前我们得先说说NSURLSessionDelegate这个代理,看下面它的API: 

/*
 * Messages related to the URL session as a whole
 @protocol NSURLSessionDelegate <NSObject>
 @optional
 */

/* The last message a session receives.  A session will only become
 * invalid because of a systemic error or when it has been
 * explicitly(明显) invalidated, in which case the error parameter will be nil.
 会话失效
 通知URL会话该会话已失效。
 如果通过调用finishTasksAndInvalidate方法使会话失效,则会话将一直等待,直到会话中的最终任务完成或失败,然后再调用此委托方法。如果您调用invalidateAndCancel方法,
 会话将立即调用此委托方法。
 对于每一个完成的后台Task调用该Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)
 和URLSession:task:didCompleteWithError:(成功或者失败都会调用)方法做处理,以上的回调代码块可以在这里调用
 - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error;

 */

/* If implemented, when a connection level authentication challenge
 * has occurred, this delegate will be given the opportunity to
 * provide authentication credentials to the underlying
 * connection. Some types of authentication will apply to more than
 * one request on a given connection to a server (SSL Server Trust
 * challenges).  If this delegate message is not implemented, the
 * behavior will be to use the default handling, which may involve user
 * interaction.
 
  如果服务器要求验证客户端身份或向客户端提供其证书用于验证时,则会调用
  在苹果开发者文档中有这样的说明
  If the initial handshake with the server requires a connection-level challenge (such as an SSL client certificate), NSURLSession calls either the URLSession:task:didReceiveChallenge:completionHandler: or URLSession:didReceiveChallenge:completionHandler: delegate method.
 
 响应来自远程服务器的会话级别认证请求,从代理请求凭据。
 这种方法在两种情况下被调用:
 1、远程服务器请求客户端证书或Windows NT LAN Manager(NTLM)身份验证时,允许您的应用程序提供适当的凭据
 2、当会话首先建立与使用SSL或TLS的远程服务器的连接时,允许您的应用程序验证服务器的证书链
 如果您未实现此方法,则会话会调用其委托的URLSession:task:didReceiveChallenge:completionHandler:方法。
 注:此方法仅处理NSURLAuthenticationMethodNTLM,NSURLAuthenticationMethodNegotiate,NSURLAuthenticationMethodClientCertificate和NSURLAuthenticationMethodServerTrust身份验证类型。对于所有其他认证方案,会话仅调用URLSession:task:didReceiveChallenge:completionHandler:方法。
 
  - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;

 */

/* If an application has received an
 * -application:handleEventsForBackgroundURLSession:completionHandler:
 * message, the session delegate will receive this message to indicate
 * that all messages previously enqueued for this session have been
 * delivered.  At this time it is safe to invoke the previously stored
 * completion handler, or to begin any internal updates that will
 * result in invoking the completion handler.
 
 如果一个应用程序收到了
 -application:handleEventsForBackgroundURLSession:completionHandler:
 消息,session委托将收到此消息指示所有消息之前进行入队这个会话交付。这个时候是安全调用先前存储完成处理器,或开始任何内部更新将导致调用完成处理器。
 
 告诉委托所有session里的消息都已发送。
 这个方法在我们写后台下载的Demo中我们是会遇到的。
 - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session API_AVAILABLE(ios(7.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
*/

/*
 下面是Task解析
 NSURLSessionTask是一个抽象子类,它有三个子类:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。这三个类封装了现代应用程序的三个基本网络任务:获取数据,比如JSON或XML,以及上传和下载文件。
*/

 

      上面我们说了NSURLSessionDelegate这个代理,接下来就是我们的NSURLSessionTaskDelegate,看到Task就知道接下来的还有我们常见的三个Task代理:

      我们先看看这个:NSURLSessionTaskDelegate,然后在一个个的说明那三个Task(data,download,stream)代理。关于uploadTask由于是继承dataTask的。

 

/*
 * Sent when the system is ready to begin work for a task with a delayed start
 * time set (using the earliestBeginDate property). The completionHandler must
 * be invoked in order for loading to proceed. The disposition provided to the
 * completion handler continues the load with the original request provided to
 * the task, replaces the request with the specified task, or cancels the task.
 * If this delegate is not implemented, loading will proceed with the original
 * request.
 *
 * Recommendation: only implement this delegate if tasks that have the
 * earliestBeginDate property set may become stale and require alteration prior
 * to starting the network load.
 *
 * If a new request is specified, the allowsCellularAccess property from the
 * new request will not be used; the allowsCellularAccess property from the
 * original request will continue to be used.
 *
 * Canceling the task is equivalent to calling the task's cancel method; the
 * URLSession:task:didCompleteWithError: task delegate will be called with error
 * NSURLErrorCancelled.
 
 告诉代理现在将开始加载延迟的URL会话任务。
 当具有延迟开始时间的后台会话任务(由earliestBeginDate属性设置)准备就绪时,将调用此方法。只有在等待网络负载时请求可能变陈旧并需要被新请求替换时,才应实现此委托方法。
 为了继续加载,委托人必须调用完成处理程序,并传递一个处理方式来指示任务应该如何进行。传递NSURLSessionDelayedRequestCancel处置等效于直接调用任务的取消。
 
   - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
   willBeginDelayedRequest:(NSURLRequest *)request
   completionHandler:(void (^)(NSURLSessionDelayedRequestDisposition disposition, NSURLRequest * _Nullable newRequest))completionHandler
   API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
 */

/* 告诉代理,在开始网络加载之前,任务正在等待,直到合适的连接可用。
 如果NSURLSessionConfiguration的waitsForConnectivity属性为true并且没有足够的连接,则调用此方法。 代表可以利用这个机会来更新用户界面;
 例如通过呈现离线模式或仅限蜂窝模式。
 此方法最多只能在每个任务中调用一次,并且仅在连接最初不可用时调用。 它永远不会被调用后台会话,因为这些会话会忽略waitsForConnectivity。

 * Sent when a task cannot start the network loading process because the current
 * network connectivity is not available or sufficient for the task's request.
 *
 * This delegate will be called at most one time per task, and is only called if
 * the waitsForConnectivity property in the NSURLSessionConfiguration has been
 * set to YES.
 *
 * This delegate callback will never be called for background sessions, because
 * the waitForConnectivity property is ignored by those sessions.
 
 - (void)URLSession:(NSURLSession *)session taskIsWaitingForConnectivity:(NSURLSessionTask *)task
 API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
 
 告诉委托远程服务器请求HTTP重定向。
 此方法仅适用于默认和临时会话中的任务。 后台会话中的任务会自动遵循重定向。
 * An HTTP request is attempting to perform a redirection to a different
 * URL. You must invoke the completion routine to allow the
 * redirection, allow the redirection with a modified request, or
 * pass nil to the completionHandler to cause the body of the redirection
 * response to be delivered as the payload of this request. The default
 * is to follow redirections.
 *
 * For tasks in background sessions, redirections will always be followed and this method will not be called.
 
  - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
  willPerformHTTPRedirection:(NSHTTPURLResponse *)response
        newRequest:(NSURLRequest *)request
  completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler;

 
 响应来自远程服务器的认证请求,从代理请求凭证。
 该方法处理任务级别的身份验证挑战。 NSURLSessionDelegate协议还提供了会话级别的身份验证委托方法。所调用的方法取决于身份验证挑战的类型:
 对于会话级挑战-NSURLAuthenticationMethodNTLM,NSURLAuthenticationMethodNegotiate,NSURLAuthenticationMethodClientCertificate或NSURLAuthenticationMethodServerTrust - NSURLSession对象调用会话委托的URLSession:didReceiveChallenge:completionHandler:方法。如果您的应用程序未提供会话委托方法,则NSURLSession对象会调用任务委托人的URLSession:task:didReceiveChallenge:completionHandler:方法来处理该挑战。
 对于非会话级挑战(所有其他挑战),NSURLSession对象调用会话委托的URLSession:task:didReceiveChallenge:completionHandler:方法来处理挑战。如果您的应用程序提供会话委托,并且您需要处理身份验证,那么您必须在任务级别处理身份验证,或者提供明确调用每会话处理程序的任务级别处理程序。会话委托的URLSession:didReceiveChallenge:completionHandler:方法不针对非会话级别的挑战进行调用。
 
 * The task has received a request specific authentication challenge.
 * If this delegate is not implemented, the session specific authentication challenge
 * will *NOT* be called and the behavior will be the same as using the default handling
 * disposition.
 
 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
 didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
 
 NOTE:注意区分上面的方法 这个是NSURLSessionDelegate代理方法
 - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;

 当任务需要新的请求主体流发送到远程服务器时,告诉委托。
 这种委托方法在两种情况下被调用:
 1、如果使用uploadTaskWithStreamedRequest创建任务,则提供初始请求正文流:
 2、如果任务因身份验证质询或其他可恢复的服务器错误需要重新发送包含正文流的请求,则提供替换请求正文流。
 注:如果代码使用文件URL或NSData对象提供请求主体,则不需要实现此功能。

 * Sent if a task requires a new, unopened body stream.  This may be
 * necessary when authentication has failed for any request that
 * involves a body stream.

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

 
 定期通知代理向服务器发送主体内容的进度。(上传进度)
 * Sent periodically to notify the delegate of upload progress.  This
 * information is also available as properties of the task.
 
  - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
    didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent
    totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;

 告诉代理该会话完成了该任务的收集指标
 * Sent when complete statistics information has been collected for the task.
 
  - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
    didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics
    API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

 告诉代理该任务完成传输数据
 * Sent as the last message related to a specific task.  Error may be
 * nil, which implies that no error occurred and this task is complete.
 
 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
    didCompleteWithError:(nullable NSError *)error;
*/

 

      下面我们一个一个的梳理这四个代理,它们和前面我们说的NSURLSessionTaskDelegate是有直接关系的,这个在看API的时候要随时留意一点,特别是uploadTask的代理。

      我们再说说这个NSURLSessionDataDelegate,他就是遵守了上面的Task代理,以及后面的download都会是遵循了上面的Task代理的。

 

/*
 @protocol NSURLSessionDataDelegate <NSURLSessionTaskDelegate>
 @optional
 * This method will not be called for background upload tasks (which cannot be converted to download tasks).
 
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
 didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler;

 
 告诉代理数据任务已更改为下载任务。
 当委托的URLSession:dataTask:didReceiveResponse:completionHandler:方法决定将数据请求的处置更改为下载时,会话将调用此委托方法为你提供新的下载任务。 在此调用之后,会话委托不会收到与原始数据任务相关的其他委托方法调用。
 * Notification that a data task has become a download task.  No
 * future messages will be sent to the data task.
 
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
 didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask;

 告诉委托数据任务已更改为流任务
 当委托的URLSession:dataTask:didReceiveResponse:completionHandler:方法决定将处置从数据请求更改为流时,会话将调用此委托方法为你提供新的流任务。 在此调用之后,会话委托不会收到与原始数据任务相关的其他委托方法调用。
 
 对于pipelined的请求,流任务将只允许读取,并且对象将立即发送委托消息URLSession:writeClosedForStreamTask :. 通过在其NSURLSessionConfiguration对象上设置HTTPShouldUsePipelining属性,或通过在NSURLRequest对象上设置HTTPShouldUsePipelining属性来为各个请求设置会话中的所有请求,可以禁用管道传输。

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

 
 告诉代理该数据任务已经收到了一些预期的数据。
 由于NSData对象通常是由许多不同的数据对象拼凑而成的,因此尽可能使用NSData的enumerateByteRangesUsingBlock:方法遍历数据,而不是使用bytes方法(将NSData对象平化为单个内存块)。
 此委托方法可能被多次调用,并且每次调用仅提供自上次调用后收到的数据。 如果需要,该应用负责积累这些数据。
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data;

 询问委托数据(或上传)任务是否应将响应存储在缓存中。
 会话在任务完成接收所有预期数据后调用此委托方法。如果未实现此方法,则默认行为是使用会话配置对象中指定的缓存策略。
 此方法的主要目的是防止特定URL的缓存或修改与URL响应关联的userInfo字典。
 只有在处理请求的NSURLProtocol决定缓存响应时才调用此方法。通常,只有满足以下所有条件时才会缓存响应:
 1、请求是针对HTTP或HTTPS URL(或你自己的支持缓存的自定义网络协议)。
 2、请求成功(状态码在200-299范围内)。
 3、提供的响应来自服务器,而不是缓存。
 4、会话配置的缓存策略允许缓存。
 5、提供的NSURLRequest对象的缓存策略(如果适用)允许缓存。
 6、服务器响应中的缓存相关头(如果存在)允许缓存。
 7、响应大小足够小,可以合理地放入缓存中。 (例如,如果您提供磁盘缓存,则响应不得超过磁盘缓存大小的5%。)
 注:如果委托实现此方法,则它必须调用completionHandler完成处理程序;否则,应用程序会泄漏内存。

 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
 willCacheResponse:(NSCachedURLResponse *)proposedResponse
 completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler;
*/

  

      接下来就是下载代理:NSURLSessionDownloadDelegate,它的代理方法就三个,但确实是我们使用比较多的,我们也看看这三个代理方法的含义

      在我们的Demo中,我们写后台下载的时候使用的也肯定是NSURLSessionDownloadDelegate,这个在Demo中有说:

 

/* 下载代理
 * Messages related to the operation of a task that writes data to a
 * file and notifies the delegate upon completion.
   @protocol NSURLSessionDownloadDelegate <NSURLSessionTaskDelegate>


 下载完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location;

 
@optional
下载进度
Sent periodically to notify the delegate of download progress.
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
        didWriteData:(int64_t)bytesWritten
        totalBytesWritten:(int64_t)totalBytesWritten
        totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

 
 下载任务已经恢复下载。
 
 参数:filrOffest:
 如果文件的缓存策略或上次修改日期阻止重新使用现有内容,则该值为零。否则,该值是一个整数,表示磁盘上不需要再次检索的字节数。
 如果可恢复的下载任务被取消或失败,可以请求resumeData对象,该对象将提供足够的信息以重新开始下载。
 稍后,你可以调用downloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:使用该数据。
 当你调用这些方法时,你会得到一个新的下载任务。只要恢复该任务,会话就会使用该新任务调用其委托的
 URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:方法,以指示恢复下载。
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
        didResumeAtOffset:(int64_t)fileOffset
        expectedTotalBytes:(int64_t)expectedTotalBytes;

*/

 

      接下来就是NSURLSessionStreamDelegate,这样我们的几个代理方法我们也就都说完了:

/*
 @protocol NSURLSessionStreamDelegate <NSURLSessionTaskDelegate>
 @optional

 告诉委托底层Socket的读取面已经关闭。
 即使当前过程没有读取,也可以调用此方法。 此方法并不表示流达到end-of-file(EOF),
 从而不能读取更多数据。
- (void)URLSession:(NSURLSession *)session readClosedForStreamTask:(NSURLSessionStreamTask *)streamTask;

 上面读这个就是写的说明
 告诉委托底层套接字的写入端已关闭。
 即使当前过程没有写入,也可以调用此方法。
- (void)URLSession:(NSURLSession *)session writeClosedForStreamTask:(NSURLSessionStreamTask *)streamTask;

 
 告诉委托流已经检测到通往主机更好的路由  下面的例子是WiFi可用了
- (void)URLSession:(NSURLSession *)session betterRouteDiscoveredForStreamTask:(NSURLSessionStreamTask *)streamTask;

 告诉委托,流任务已完成,由于流任务调用captureStreams方法。
 此委托方法仅在流任务的所有入队读取和写入操作完成后才会调用。
- (void)URLSession:(NSURLSession *)session streamTask:(NSURLSessionStreamTask *)streamTask
        didBecomeInputStream:(NSInputStream *)inputStream
        outputStream:(NSOutputStream *)outputStream;
*/

 

 

NSURLSessionTaskTransactionMetrics和NSURLSessionTaskMetrics


 

 

     NSURLSessionTaskTransactionMetrics 主要使用这个API获取每个阶段的网络请求时常,等数据,来分析对应的网络请求。

/*
   This class defines the performance(性能) metrics collected for a request/response transaction     during the task execution.执行
主要使用这个API获取每个阶段的网络请求时常,等数据,来分析对应的网络请求。
   API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0))
   @interface NSURLSessionTaskTransactionMetrics : NSObject
*/

/*
    presents 礼物复数  表现
    Represents 代表 the transaction request.
    @property (copy, readonly) NSURLRequest *request;
 */

/*
   如果发生错误并且没有生成响应,则可以为nil
   @property (nullable, copy, readonly) NSURLResponse *response;
 */

/*
 * fetchStartDate returns the time when the user agent started fetching the resource, whether or not the resource was retrieved from the server or local resources.
 * 用户代理开始获取资源的时间,无论是否从服务器或本地资源中检索资源。
 * The following metrics will be set to nil, if a persistent connection was used or the resource was retrieved from local resources:

 *   domainLookupStartDate
 *   domainLookupEndDate
 *   connectStartDate
 *   connectEndDate
 *   secureConnectionStartDate
 *   secureConnectionEndDate
     @property (nullable, copy, readonly) NSDate *fetchStartDate;
 */

/* 用户代理启动资源名称查找之前的时间。
    domainLookupStartDate returns the time immediately before the user agent started the name lookup for the resource.
   @property (nullable, copy, readonly) NSDate *domainLookupStartDate;
 */

/* 名称查询完成后的时间。
 * domainLookupEndDate returns the time after the name lookup was completed.
   @property (nullable, copy, readonly) NSDate *domainLookupEndDate;
 */

/* 用户代理开始建立到服务器的连接之前的时间。
    connectStartDate is the time immediately before the user agent started establishing the connection to the server.
  
    For example, this would correspond to the time immediately before the user agent started trying to establish the TCP connection.
   @property (nullable, copy, readonly) NSDate *connectStartDate;
*/

/* 如果使用加密连接,则secureConnectionStartDate是用户代理刚刚开始安全握手以保护当前连接之前的时间。如果未使用加密连接,则此属性设置为零。
   If an encrypted 加密 connection was used, secureConnectionStartDate is the time immediately before the user agent 代理 started the
   security 安全 handshake to secure the current connection.
   For example, this would correspond to the time immediately before the user agent started the TLS handshake.
   If an encrypted connection was not used, this attribute is set to nil.
   @property (nullable, copy, readonly) NSDate *secureConnectionStartDate;
 */

/* 如果使用加密连接,则secureConnectionEndDate是安全握手完成后的时间。如果未使用加密连接,则此属性设置为零
 * If an encrypted connection was used, secureConnectionEndDate is the time immediately after the security handshake completed.
 *
 * If an encrypted connection was not used, this attribute is set to nil.
   @property (nullable, copy, readonly) NSDate *secureConnectionEndDate;
 */

/* 用户代理完成与服务器建立连接后的时间,包括完成与安全相关的握手和其他握手
 * connectEndDate is the time immediately after the user agent finished establishing the connection to the server, including completion of security-related and other handshakes.
   @property (nullable, copy, readonly) NSDate *connectEndDate;
 */

/* 用户代理开始请求源之前的时间,无论是从服务器还是从本地资源中检索资源。
    requestStartDate is the time immediately before the user agent started requesting the source, regardless of whether the resource was retrieved from the server or local resources.
    For example, this would correspond to the time immediately before the user agent sent an HTTP GET request.
   @property (nullable, copy, readonly) NSDate *requestStartDate;
 */

/* 用户代理完成请求源后的时间,无论资源是从服务器还是从本地资源中检索
    requestEndDate is the time immediately after the user agent finished requesting the source, regardless of whether the resource was retrieved from the server or local resources.
    For example, this would correspond to the time immediately after the user agent finished sending the last byte of the request.
   @property (nullable, copy, readonly) NSDate *requestEndDate;
 */

/* 用户代理刚收到服务器或本地资源响应的第一个字节后的时间。
   responseStartDate is the time immediately after the user agent received the first byte of the response from the server or from local resources.
  
   For example, this would correspond to the time immediately after the user agent received the first byte of an HTTP response.
   @property (nullable, copy, readonly) NSDate *responseStartDate;
 */

/* 用户代理收到资源的最后一个字节后的时间。
   responseEndDate is the time immediately after the user agent received the last byte of the resource.
   @property (nullable, copy, readonly) NSDate *responseEndDate;
 */

/* 用于获取资源的网络协议,由ALPN协议ID标识序列[RFC7301]标识。如果配置了代理并建立了隧道连接,则此属性将返回隧道协议的值。
 * The network protocol used to fetch the resource, as identified by the ALPN Protocol ID Identification Sequence [RFC7301].
 * E.g., h2, http/1.1, spdy/3.1.
 *
 * When a proxy is configured AND a tunnel connection is established, then this attribute returns the value for the tunneled protocol.
 *
 * For example:
 * If no proxy were used, and HTTP/2 was negotiated, then h2 would be returned.
 * If HTTP/1.1 were used to the proxy, and the tunneled connection was HTTP/2, then h2 would be returned.
 * If HTTP/1.1 were used to the proxy, and there were no tunnel, then http/1.1 would be returned.
 
   @property (nullable, copy, readonly) NSString *networkProtocolName;
 *
 */

/* 如果使用代理连接来获取资源,则此属性设置为YES。
 * This property is set to YES if a proxy connection was used to fetch the resource.
 
   @property (assign, readonly, getter=isProxyConnection) BOOL proxyConnection;
 */

/* 如果使用持续连接来获取资源,则此属性设置为YES
    This property is set to YES if a persistent connection was used to fetch the resource.
    @property (assign, readonly, getter=isReusedConnection) BOOL reusedConnection;
 */

/* 指示资源是否已从本地缓存中加载,推送或检索。
    Indicates whether the resource was loaded, pushed or retrieved from the local cache.
    @property (assign, readonly) NSURLSessionTaskMetricsResourceFetchType resourceFetchType;
 */

/* API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0))
    @interface NSURLSessionTaskMetrics : NSObject
 */

/* 包含为在任务执行期间创建的每个请求/响应事务收集的度量标准。
    transactionMetrics array contains the metrics collected for every request/response transaction created during the task execution.
    @property (copy, readonly) NSArray<NSURLSessionTaskTransactionMetrics *>       transactionMetrics;
 */

/* 从任务创建时间到任务完成时间的时间间隔。
   @property (copy, readonly) NSDateInterval *taskInterval;

 */

/* 记录的重定向的数量。
    redirectCount is the number of redirects that were recorded.
    @property (assign, readonly) NSUInteger redirectCount;
 */

 

最后小 demo


 

 

      最后是一个断点下载和后台下载的一个Demo,具体的Demo代码我就不再具体的讲解了,因为在Demo中加了很多的注释。

      由于这个Demo是写在以前的关于AVFoundation的Demo里面,具体的Demo是在NSURLSession文件中。

      还有前面关于API的注释也是在写URLSessionManager.h文件中,需要的可以翻翻去看看,关于NSURLSession暂时就先说这么多,有问题可以加我QQ 1872684219  

      Demo 点击这里下载

 

版权声明:本文为taoxu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/taoxu/p/9003457.html