NSURLSession和NSURLConnection的区别

NSURLConnection主要API如下

/*
创建一个NSURLConnection,只建立连接,并没有下载数据
request: 请求内容
delegate:NSURLConnectionDelegate,NSURLConnection实例会强引用delegate,直到回调didFinishLoading,didFailWithErrorNSURLConnection.cancel调用
startImmediately : 是否立即下载数据,YES立即下载,自动把connection加入到当前的主线程runloop中,且任务完成的结果会在主线程的runloop中回调。NO,只建立连接,不下载数据,需要手动把connection加入到指定的runloop中。需要手动【connection start】开始下载数据。
*/
- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate startImmediately:(BOOL)startImmediately API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.5,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
其实就是用的[self initWithRequest:request delegate:delegate startImmediately:YES];不需要显示的在去调用【connection start】
*/
- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
其实就是用的[self initWithRequest:request delegate:delegate startImmediately:YES];不需要显示的在去调用【connection start】
*/
+ (nullable NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
建立连接时用的请求
*/
@property (readonly, copy) NSURLRequest *originalRequest API_AVAILABLE(macos(10.8), ios(5.0), watchos(2.0), tvos(9.0));
/*
建立连接的请求进过认证协议可能会改变
*/
@property (readonly, copy) NSURLRequest *currentRequest API_AVAILABLE(macos(10.8), ios(5.0), watchos(2.0), tvos(9.0));
/*
开始下载数据,通过- (instancetype)initWithRequest:(NSURLRequest
 *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately
 初始化的实例,调用【connection start】
*/
- (void)start API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/*
断开网络连接,取消请求,cancel方法不能保证代理回调立即不会调用(应该是请求到的数据,只能传给代理),cancel会release delegate
*/
- (void)cancel;
/*
将connection实例回调加入到一个runloop,NSURLConnectionDelegate回调会在这个runloop中响应注意该方法不能跟setDelegateQueue同时设置,只能选择一个。
*/
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/*
取消在这个runloop中的回调
*/
- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/*
如果设置了queue,回调将会在这个queue上进行,回调一次就生成了一个NSBlockOperation加入到了queue中注意该方法不能跟scheduleInRunLoop同时设置,只能选择一个。
*/
- (void)setDelegateQueue:(nullable NSOperationQueue*) queue API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
/*
类方法创建一个同步请求。这个方法是建立在异步的基础上,然后阻塞当前线程实现的 
response:响应头信息,传递一个二维指针 
error:请求结果的状态
*/
+ (nullable NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse * _Nullable * _Nullable)response error:(NSError **)error API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
发起一个异步请求
queue:completionHandler会运行在这个queue中
completionHandler:请求回调block
 */
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
                          queue:(NSOperationQueue*) queue
              completionHandler:(void (^)(NSURLResponse* _Nullable response, NSData* _Nullable data, NSError* _Nullable connectionError)) handler API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.7,10.11), ios(5.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;

NSURLSession主要API如下(所有创建task的方法,只要带有completionHandler这个参数的,均表示为请求过程中不会触发代理方法。所有不带有completionHandler这个参数的,均会走代理方法流程。如果你实现了URLSession:didReceiveChallenge:completionHandler:方法又没有在该方法调用completionHandler,请求就会遭到阻塞。)

/*
直接创建,使用当前设置的全局NSURLCache,
NSHTTPCookieStorage和NSURLCredentialStorage对象。
*/
@property (class, readonly, strong) NSURLSession *sharedSession;
/*
第一个粒度较低就是根据刚才创建的Configuration创建一个Session,系统默认创建一个新的OperationQueue处理Session的消息。自定义配置文件, 设置代理, 大部分时间我们都是用这个
*/
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
/*
第二个粒度比较高,可以设定回调的delegate(注意这个回调delegate会被强引用),并且可以设定delegate在哪个OperationQueue回调,如果我们将其设置为[NSOperationQueue mainQueue]就能在主线程进行回调非常的方便。
*/
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
@property (readonly, retain) NSOperationQueue *delegateQueue;
@property (nullable, readonly, retain) id <NSURLSessionDelegate> delegate;
@property (readonly, copy) NSURLSessionConfiguration *configuration;
@property (nullable, copy) NSString *sessionDescription;
/*
调用finishTasksAndInvalidate方法让任务继续运行,在运行结束时取消session。
不再需要session的时候调用invalidateAndCancel方法停止所有任务并使session失效。
session失效之后会给URLSession:didBecomeInvalideWithError:方法发送消息,当这个方法返回之后,session不再对delegate持有强引用。
*/
- (void)finishTasksAndInvalidate;
- (void)invalidateAndCancel;
/*
NSURLSession设置过代理后,需要在最后(比如控制器销毁的时候)调用session的invalidateAndCancel或者resetWithCompletionHandler,才不会有内存泄露。清空cookies, 缓存和证书存储, 移除所有磁盘文件, 清理正在执行的下载任务, 确保未来能响应一个新的socket请求
*/
- (void)resetWithCompletionHandler:(void (^)(void))completionHandler; 
/*
清除硬盘上的cookies和证书, 清理暂时的缓存, 确保未来能响应一个新的TCP请求
*/
- (void)flushWithCompletionHandler:(void (^)(void))completionHandler; 
/*
异步调用session中所有upload, download, data tasks的completion回调.
*/
- (void)getTasksWithCompletionHandler:(void (^)(NSArray<NSURLSessionDataTask *> *dataTasks, NSArray<NSURLSessionUploadTask *> *uploadTasks, NSArray<NSURLSessionDownloadTask *> *downloadTasks))completionHandler;
- (void)getAllTasksWithCompletionHandler:(void (^)(NSArray<__kindof NSURLSessionTask *> *tasks))completionHandler API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));
/*
创建NSURLSessionDataTask
*/
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;
/*
创建NSURLSessionUploadTask
*/
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;
/*
创建NSURLSessionDownloadTask
*/
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
/*
通过一个指定的IP地址, 端口号来创建一个NSURLSessionStreamTask
*/
- (NSURLSessionStreamTask *)streamTaskWithHostName:(NSString *)hostname port:(NSInteger)port API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
/*
通过一个指定的NSNetService对象来创建NSURLSessionStreamTask
*/
- (NSURLSessionStreamTask *)streamTaskWithNetService:(NSNetService *)service API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;

NSURLSessionConfiguration主要API如下

/*
内置的配置对象
通过类方法,NSURLSessionConfiguration提供了适用于不同情况的配置对象,它们的一些配置属性设置了不同的默认值。

+ defaultSessionConfiguration,默认的配置对象,持久化存储缓存,证书,cookie。
+ ephemeralSessionConfiguration,不持久化存储缓存,证书,cookie的配置。所有相关内容只保存在内存中,当 session 失效或应用终止,所有内容被清空。该配置可提高私密性,因为不会向硬盘上写入数据。
+ backgroundSessionConfigurationWithIdentifier:,适用于在后台上传和下载文件的网络请求。当应用被系统终止并重启,传入的参数 identifier 可用来重新创建配置和 session 对象,以便恢复中断的下载任务。如果是用户主动终止程序,则不会有上述行为。
*/
/*
一般模式(default):工作模式类似于原来的NSURLConnection,可以使用缓存的Cache,Cookie,鉴权。
*/
@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;
/*
及时模式(ephemeral):不使用缓存的Cache,Cookie,鉴权。 仅内存缓存, 不做磁盘缓存的配置
*/
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;
/*
后台模式(background):在后台完成上传下载,创建Configuration对象的时候需要给一个NSString的ID用于追踪完成工作的Session是哪一个(后面会讲到)。
*/
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
/*
普通配置项
identifier,用于唯一标识一个后台下载的 session,当系统重启被自动关闭的应用时,可以通过这个标识符,重新创建 configuration 和 session 对象来恢复中断的下载。
HTTPAdditionalHeaders,一个 dictionary,包含了需要额外添加到 session 中所有 request 的 header,如User-Agent。不应添加
Authorization、Connection、Host和WWW-Authenticate。如果 request 中已存在某一 header,则使用 request 中的值,该 dictionary 默认为空。
networkServiceType,NSURLRequestNetworkServiceType类型,network service type 影响着操作系统对于网络传输的优先级排列,进而影响系统电量、性能的消耗。默认值是NSURLNetworkServiceTypeDefault。
allowsCellularAccess,布尔值,指明在移动网络下是否可发起请求。
timeoutIntervalForRequest,请求的超时时间,默认值为60秒。
timeoutIntervalForResource,所有资源下载或上传完成的超时时间,中间请求失败可重新请求,单位为秒,默认时间为7天。
sharedContainerIdentifier,用于应用扩展与应用间的后台会话的扩展容器。
*/
@property (nullable, readonly, copy) NSString *identifier;
@property (nullable, copy) NSDictionary *HTTPAdditionalHeaders;
@property NSURLRequestNetworkServiceType networkServiceType;
@property BOOL allowsCellularAccess;
@property NSTimeInterval timeoutIntervalForRequest;
@property NSTimeInterval timeoutIntervalForResource;
@property (nullable, copy) NSString *sharedContainerIdentifier API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
/*
后台下载配置项
sessionSendsLaunchEvents,布尔值,说明在 session task 完成或者需要验证时,是否在后台运行应用。当设为 YES 时,系统会自动启动或运行应用,并调用 AppDelegate 中的方法
application:handleEventsForBackgroundURLSession:completionHandler:,通过参数提供上述提到的唯一标识后台下载 session 的 identifier。
discretionary,布尔值,说明在下载时是否由系统统一安排资源。
*/
@property BOOL sessionSendsLaunchEvents API_AVAILABLE(ios(7.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
@property (getter=isDiscretionary) BOOL discretionary API_AVAILABLE(macos(10.10), ios(7.0), watchos(2.0), tvos(9.0));
/*
安全相关配置项
TLSMaximumSupportedProtocol,SSLProtocol 类型,请求支持的最高 TLS 版本,默认值是 kTLSProtocol12,即 TLS1.2。
TLSMinimumSupportedProtocol,SSLProtocol 类型,请求支持的最低 TLS 版本,默认值是 kSSLProtocol3,即 SSL3.0。
URLCredentialStorage,管理需要验证的请求证书。
*/
@property SSLProtocol TLSMinimumSupportedProtocol;
@property SSLProtocol TLSMaximumSupportedProtocol;
@property (nullable, retain) NSURLCredentialStorage *URLCredentialStorage;
/*
HTTP相关配置项
HTTPMaximumConnectionsPerHost,session 内一个域名的最大同时连接数。
HTTPShouldUsePipelining,布尔值,说明 session 内的 task 是否使用 HTTP pipelining。
connectionProxyDictionary,字典类型,保存了连接代理的相关信息,默认为 NULL。
*/
@property NSInteger HTTPMaximumConnectionsPerHost;
@property BOOL HTTPShouldUsePipelining;
@property (nullable, copy) NSDictionary *connectionProxyDictionary;
/*
HTTP cookie 相关配置项
HTTPCookieAcceptPolicy,接收 cookie 的策略,
NSHTTPCookieAcceptPolicy类型,默认值是
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain
HTTPCookieStorage,对于default 和 background session,该属性值为NSHTTPCookieStorage的单例对象,而 ephemeral session 的默认值为一个私有的NSHTTPCookieStorage对象,只将 cookie 保存在内存中,如果 session 不想保存 cookie,可将该属性设为 nil。
HTTPShouldSetCookies,布尔值,指明请求时是否携带 cookie 信息。
*/
@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy;
@property (nullable, retain) NSHTTPCookieStorage *HTTPCookieStorage;
@property BOOL HTTPShouldSetCookies;
/*
缓存策略配置项
`URLCache`,用于保存缓存响应的[NSURLCache]对象,default session 默认使用`NSURLCache`的单例对象,background session 的默认值为 nil,而 ephemeral session 的默认值是一个私有的`NSURLCache`对象,数据只保存在内存中。如果不想使用缓存,可直接设置该值为 nil。
`requestCachePolicy`,枚举类型`NSURLRequestCachePolicy`,指明了请求使用缓存响应的策略。
// 默认值,使用协议本身的缓存逻辑。
NSURLRequestUseProtocolCachePolicy
// 不使用现有缓存,数据需要从原始地址加载。
NSURLRequestReloadIgnoringLocalCacheData
// 无论缓存是否过期,先使用本地缓存数据。如果缓存中没有请求所对应的数据,那么从原始地址加载数据。
NSURLRequestReturnCacheDataElseLoad
// 无论缓存是否过期,先使用本地缓存数据。如果缓存中没有请求所对应的数据,那么放弃从原始地址加载数据,请求视为失败。
NSURLRequestReturnCacheDataDontLoad
*/
@property (nullable, retain) NSURLCache *URLCache;
@property NSURLRequestCachePolicy requestCachePolicy;
/*
自定义协议配置项
protocolClasses,由自定义实现的NSURLProtocol子类的 Class 对象组成的数组,配置了 session 支持的自定义协议。
*/
@property (nullable, copy) NSArray<Class> *protocolClasses;
/*
iOS11新增加API。一个更加灵活的网络请求API,它能够等待直到你的手机连接上了安全的网络,如果是不安全的网络则该网络请求不会调用。
*/
@property BOOL waitsForConnectivity API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/*
MutliPath TCP
Multipath protocols for Multipath Devices(适合多链路设备的多链路 TC P协议)增加了对使用多个接口(如Wi-Fi和Cellular)的支持
通过扩展 URLSessionConfiguration 以支持 IETF、RFC 6824中定义的多路径TCP传输单个数据流。有关更多信息,请参阅URLSessionConfiguration.MultipathServiceType。
*/
@property NSURLSessionMultipathServiceType multipathServiceType API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);
/*
为创建的任何tcp套接字启用扩展后台空闲模式。 启用此模式会要求系统保持打开状态,并在进程移动到后台时延迟回收
*/
@property BOOL shouldUseExtendedBackgroundIdleMode API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));

NSURLSessionTask主要API如下

/*
相关信息
originalRequest,创建 task 时对应的请求对象。
currentRequest,当响应为重定向到其他 URL 时,该值会改变。
response,服务端返回的NSURLResponse对象。
taskIdentifier,NSUInteger类型,task 在 session 内的唯一标识。
error,当任务失败时的NSError对象。
taskDescription,可给任务设置一个可读的描述,在如果需要界面展示时使用。
*/
@property (nullable, readonly, copy) NSURLRequest  *originalRequest;
@property (nullable, readonly, copy) NSURLRequest  *currentRequest; 
@property (nullable, readonly, copy) NSURLResponse *response; 
@property (readonly)                 NSUInteger    taskIdentifier;
@property (nullable, copy) NSString *taskDescription;

@property (readonly, strong) NSProgress *progress API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
@property (nullable, copy) NSDate *earliestBeginDate API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
@property int64_t countOfBytesClientExpectsToSend API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
@property int64_t countOfBytesClientExpectsToReceive API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/*
进度信息
countOfBytesExpectedToSend,请求体的字节数,系统根据 header 中的 Content-Length 字段,或者作为请求体的NSData或文件的大小来设置该值。
countOfBytesSent,已发送的请求体字节数,当该值变化,会触发代理方法
-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
countOfBytesExpectedToReceive,响应体期望收到的字节数,根据响应 header 中的 Content-Length 字段,若未指明,则该值为
NSURLSessionTransferSizeUnknown(-1)
countOfBytesReceived,已收到的响应体字节数,当该值变化,会触发代理方法- URLSession:dataTask:didReceiveData:或
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
*/
@property (readonly) int64_t countOfBytesReceived;
@property (readonly) int64_t countOfBytesSent;
@property (readonly) int64_t countOfBytesExpectedToSend;
@property (readonly) int64_t countOfBytesExpectedToReceive;
- (void)cancel;
/*
控制 task 的状态
task 的当前状态由枚举类型NSURLSessionTaskState的属性 state 表示,包含以下几种可能的值:
typedef NS_ENUM(NSInteger, NSURLSessionTaskState) {
    NSURLSessionTaskStateRunning = 0,
    NSURLSessionTaskStateSuspended = 1,
    NSURLSessionTaskStateCanceling = 2, /*当向task发送cancel消息后,会转变为该状态,代理会收到- URLSession:task:didCompleteWithError:消息*/
    NSURLSessionTaskStateCompleted = 3, /*完成状态不包括被取消的情况*/
};
通过NSURLSession 创建的 task 默认是状态是 suspended,调用- resume 方法后,task 的状态变为 running。通过- suspend 方法可以将 task 重新变为挂起状态,当恢复 running 状态时,download task 可以从中断的地方继续传输,而其他 task 都需要重新开始。当调用- cancel 方法后,task 变为 canceling 状态,在发送给 delegate 的URLSession:task:didCompleteWithError:消息中,error 参数的 domain 为NSURLErrorDomain,code 为NSURLErrorCancelled。
*/
@property (readonly) NSURLSessionTaskState state;
@property (nullable, readonly, copy) NSError *error;
- (void)suspend;
- (void)resume;
/*
优先级
task 有一个priority属性,接受0到1之间的浮点数,通过每一个 task 不同的 priority 值,可以提示系统 task 执行的优先级,1为最高,0为最低。默认值是NSURLSessionTaskPriorityDefault,即 0.5。系统提供了3个常量值:
NSURLSessionTaskPriorityDefault //0.5
NSURLSessionTaskPriorityLow // 0
NSURLSessionTaskPriorityHigh // 1
*/
@property float priority API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

NSURLSessionDataTask是NSURLSessionTask的子类,无单独API。(主要使用在请求一些比较简单的数据,比如我们常用的JSON数据。)
NSURLSessionUploadTask是NSURLSessionDataTask的子类,无单独API。(这个和上面那个task对应,主要是给服务器发送文件数据所使用的。)
NSURLSessionDownloadTask是NSURLSessionTask的子类,主要API如下(这个主要使用在进行一些文件的下载,它可以针对一些大文件的网络请求做更多的处理, 比如获取下载进度,文件的断点续传等等牛逼事情。)

/*
调用了基类NSURLSessionTask中的- cancel方法,参数 completionHandler 要求传入一个 block,用来处理已传输的数据 resume data,这个 resume data 将来可用于 session 的- downloadTaskWithResumeData:方法,以便继续中断的下载。
*/
- (void)cancelByProducingResumeData:(void (^)(NSData * _Nullable resumeData))completionHandler;

NSURLSessionStreamTask是NSURLSessionTask的子类,主要API如下(提供TCP/IP的一个链接入口,方便进行传输。)

/*
针对直接进行TCP/IP连接的网络操作API,此次带来新的NSURLSessionStreamTask来,
代替NSInputStream和NSOutputStream,并且API使用起来便捷容易。
*/
- (void)readDataOfMinLength:(NSUInteger)minBytes maxLength:(NSUInteger)maxBytes timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSData * _Nullable data, BOOL atEOF, NSError * _Nullable error))completionHandler;
/*
异步写数据操作
*/
- (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSError * _Nullable error))completionHandler;
- (void)captureStreams;
- (void)closeWrite;
- (void)closeRead;
- (void)startSecureConnection;
- (void)stopSecureConnection;

NSURLSessionTaskMetrics 和 NSURLSessionTaskTransactionMetrics
对发送请求/DNS查询/TLS握手/请求响应等各种环节时间上的统计。更易于我们检测,分析我们App的请求缓慢到底是发生在哪个环节,并对此进行优化提升我们APP的性能,NSURLSessionTaskMetrics对象与NSURLSessionTask对象一一对应。每个NSURLSessionTaskMetrics对象内有3个属性 :
taskInterval : task从开始到结束总共用的时间
redirectCount : task重定向的次数
transactionMetrics : 一个task从发出请求到收到数据过程中派生出的每个子请求,它是一个装着许多NSURLSessionTaskTransactionMetrics对象的数组。
API很简单, 就一个方法 : - (void)URLSession: task: didFinishCollectingMetrics:, 当收集完成的时候就会调用该方法.
NSURLSessionTaskMetrics主要API如下

 */
@property (copy, readonly) NSArray<NSURLSessionTaskTransactionMetrics *> *transactionMetrics;
@property (copy, readonly) NSDateInterval *taskInterval;
@property (assign, readonly) NSUInteger redirectCount;
-(instancetype)init;

NSURLSessionTaskTransactionMetrics主要API如下

@property (copy, readonly) NSURLRequest *request;
@property (nullable, copy, readonly) NSURLResponse *response;
@property (nullable, copy, readonly) NSDate *fetchStartDate;
@property (nullable, copy, readonly) NSDate *domainLookupStartDate;
@property (nullable, copy, readonly) NSDate *domainLookupEndDate;
@property (nullable, copy, readonly) NSDate *connectStartDate;
@property (nullable, copy, readonly) NSDate *secureConnectionStartDate;
@property (nullable, copy, readonly) NSDate *secureConnectionEndDate;
@property (nullable, copy, readonly) NSDate *connectEndDate;
@property (nullable, copy, readonly) NSDate *requestStartDate;
@property (nullable, copy, readonly) NSDate *requestEndDate;
@property (nullable, copy, readonly) NSDate *responseStartDate;
@property (nullable, copy, readonly) NSDate *responseEndDate;
@property (nullable, copy, readonly) NSString *networkProtocolName;
@property (assign, readonly, getter=isProxyConnection) BOOL proxyConnection;
@property (assign, readonly, getter=isReusedConnection) BOOL reusedConnection;
@property (assign, readonly) NSURLSessionTaskMetricsResourceFetchType resourceFetchType;
-(instancetype)init;

NSURLSession的优势和好处
1.后台上传和下载 : 当你创建NSURLSession的时候你只需配置一个选项即可,你便可以进行所有的后台网络任务。这将有对你的电池寿命有利,它支持UIKit多任务并且当切换线程的时候使用相同的代理模型。
2.使你的网络操作可以暂停和恢复 :你稍后将会看到,任何使用NSURLSession API的网络任务都可以被暂停,停止,重新开始。而没有使用NSOperation子类的必要。
3.可配置的容器:对于放进里面的请求而言每一个NSURLSession都是可配置的。例如,假如你需要设置一个HTTP header选项,你只需要设置一次然后每个在session中的请求就都会有相同的配置了。
4.可子类化和私密存储: NSURLSession是可子类化的并且你可以配置一个session用来作为私密存储在某个会话中。这允许你拥有私密存储对象在全局状态下。
5.优化的授权处理机制:授权被完成基于某个特定的连接。当使用NSURLConnection的时候假如发生了一处授权改变,这个改变将返回一个随意的请求,你不能确定你具体得到的那个。使用NSURLSession的话,代理回来处理授权。
6.丰富的代理模型:NSURLConnection有些基于block的同步方法,然而代理就不能使用它们了。当一个请求建立了无论它是成功还是失败,哪怕需要授权。使用NSURLSession就就可以混合接入,使用基于block的异步方法同时也可以设置代理来处理授权。
7.通过文件系统上传和下载:苹果鼓励把(文件内容)数据跟(URL和一些设置)元数据分开。

NSURLSession与NSURLConnection 的不同主要表现在以下几方面:
(1) NSURLConnection 是 iOS2.0后推出的
NSURLSession 是iOS7.0后推出的,用于代替 NSURLConnection.
(2)下载任务方式
NSURLConnection 使用异步回调,先将数据下载到内存,等下载完毕后,再写入沙盒.如果文件很大,会导致内存暴涨; 并且,使用异步回调无法监听下载进度.所以使用 NSURLConnection下载的时候,使用代理回调监听下载进度,并且下载过程中要手动管理内存,使用起来比较麻烦.而使用NSURLSession的时候,block 和代理可以同时起作用,并且可以直接从文件系统上传、下载,不会出现内存暴涨的情况. 下载文件的时候,默认会将文件下载到沙盒的 tmp文件夹中,不会占多少用内存. 但是在下载完成后,会删除文件,所以要在下载完成或者其他需要的地方,增加保存文件的代码.
(3)请求方式的控制
NSURLConnection实例化对象,实例化开始,默认请求就发送(同步发送),不需要调用start方法。而cancel 可以停止请求的发送,停止后不能继续访问,需要创建新的请求。NSURLSession有三个控制请求的方法,取消(cancel),暂停(suspend),继续(resume),暂停后可以通过继续恢复当前的请求任务。
(4)断点续传实现方式
NSURLConnection进行断点下载,通过设置访问请求的HTTPHeaderField的Range属性,开启运行循环,NSURLConnection的代理方法作为运行循环的事件源,接收到下载数据时代理方法就会持续调用,并使用NSOutputStream(或者通过文件指针)管道流进行数据保存。NSURLSession进行断点下载,当暂停下载任务后,如果 downloadTask (下载任务)为非空,调用 cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler 这个方法,这个方法接收一个参数,完成处理代码块,这个代码块有一个 NSData 参数 resumeData,如果 resumeData 非空,我们就保存这个对象到视图控制器的 resumeData 属性中。在点击再次下载时,通过调用 [ [self.session downloadTaskWithResumeData: self.resumeData]resume]方法进行继续下载操作。经过以上比较可以发现,使用NSURLSession进行断点下载更加便捷。
(5) NSURLSession 可以设置配置信息
NSURLSession的构造方法
(sessionWithConfiguration: delegate:delegateQueue)中有一个 NSURLSessionConfiguration类的参数可以设置配置信息,其决定了cookie,安全和高速缓存策略,最大主机连接数,资源管理,网络超时等配置。NSURLConnection不能进行这个配置,相比于 NSURLConnection 依赖于一个全局的配置对象,缺乏灵活性而言,NSURLSession 有很大的改进了。
NSURLSession可以设置三种配置信息,分别通过调用三个类方法返回配置对象:
+(NSURLSessionConfiguration *) defaultSessionConfiguration,配置信息使用基于硬盘的持久化Cache,保存用户的证书到钥匙串,使用共享cookie存储;
+(NSURLSessionConfiguration *)ephemeralSessionConfiguration 配置信息和default大致相同。除了,不会把cache,证书,或者任何和Session相关的数据存储到硬盘,而是存储在内存中,生命周期和Session一致。比如浏览器无痕浏览等功能就可以基于这个来做;
+(NSURLSessionConfiguration *) backgroundSessionConfigurationWithIdentifier:(NSString *)identifier 配置信息可以创建一个可以在后台甚至APP已经关闭的时候仍然在传输数据的session。
注意,后台Session一定要在创建的时候赋予一个唯一的identifier,这样在APP下次运行的时候,能够根据identifier来进行相关的区分。如果用户关闭了APP,IOS 系统会关闭所有的background Session。而且,被用户强制关闭了以后,IOS系统不会主动唤醒APP,只有用户下次启动了APP,数据传输才会继续。
(6)NSURLSession 支持HTTP 2.0

链接
http://ios.jobbole.com/93098/
https://yq.aliyun.com/articles/221561
http://www.guiyongdong.com/2016/11/18/NSURLSession%E4%B8%8ENSURLConnection%E5%8C%BA%E5%88%AB/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容