NSURLSession 所有的都在这里(一)

 

这篇文章会有什么?


 

      在这篇文章中把NSURLSession.h文件集体梳理一遍,把里面的每个属性、代理和方法都拿出来说说,通过这篇文章我相信对于NSURLSession这一块的东西会梳理的比较全面一点,你掌握了NSURLSession对于iOS网络处理理解的就会有点深度了,而不是停留在AF的层面,理解了NSURLSession再去看AFNetWorking的源码会有很大的帮助。 最后再通过最后面一个Demo,把NSURLSession的一些日常中的使用再过一遍,包括你经常会听到的后台下载、断点下载、断点续传等等都有代码介绍。

      在这里我们再顺便说说NSURLRequest,因为你在能看到NSURLSession的地方肯定能看到NSURLRequest。下面我们就从NSURLRequest开始总结。

 

NSURLRequest


 

      关于NSURLRequest基本的用法这里不再讨论,相信都了解,我们直接看看它的API,还是喜欢从API入手了解一个类。

      当然,我们也不用每一个属性那样去解释,有些的确是太简单了,直接从感觉需要我们梳理一下的地方入手,具体的每一个属性建议大家自己去看看头文件了解。

      下面说的点对着这NSURLRequest头文件更容易理解:

/*!
 @method requestWithURL:cachePolicy:timeoutInterval:
 @abstract Allocates and initializes a NSURLRequest with the given
 URL and cache policy.
 @param URL The URL for the request.
 @param cachePolicy The cache policy for the request.
 @param timeoutInterval The timeout interval for the request. See the
 commentary for the <tt>timeoutInterval</tt> for more information on
 timeout intervals.
 @result A newly-created and autoreleased NSURLRequest instance.
 
 这个是类方法的初始化方法,参数就是缓存策略和超时时间
 这里引入了这个NSURLRequestCachePolicy缓存策略的枚举类型,下面梳理这个枚举。
 typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
 {
         默认缓存策略
         NSURLRequestUseProtocolCachePolicy = 0,
 
         URL应该加载源端数据,不使用本地缓存数据
         NSURLRequestReloadIgnoringLocalCacheData = 1,
 
         本地缓存数据、代理和其他中介都要忽视他们的缓存,直接加载源数据
         NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
 
         从服务端加载数据,完全忽略缓存。和NSURLRequestReloadIgnoringLocalCacheData一样
         NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
 
         使用缓存数据,忽略其过期时间;只有在没有缓存版本的时候才从源端加载数据
         NSURLRequestReturnCacheDataElseLoad = 2,
 
         只使用cache数据,如果不存在cache,就请求失败,不再去请求数据  用于没有建立网络连接离线模式
         NSURLRequestReturnCacheDataDontLoad = 3,

         指定如果已存的缓存数据被提供它的源段确认为有效则允许使用缓存数据响应请求,否则从源段加载数据。
         NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
 };
 
 */
+ (instancetype)requestWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval;

 

       我们再接着往下看:

       这里说一下NS_DESIGNATED_INITIALIZER 和 NS_UNAVAILABLE 这两个宏,这两个宏相信你要是经常看头文件的话是很容易碰到的。

/*!
 @abstract Returns the cache policy of the receiver.
 @result The cache policy of the receiver.
 缓存策略
 */
 @property (readonly) NSURLRequestCachePolicy cachePolicy;


/*!
 @abstract Returns the timeout interval of the receiver.
 @discussion The timeout interval specifies the limit on the idle
 interval alloted to a request in the process of loading. The "idle
 interval" is defined as the period of time that has passed since the
 last instance of load activity occurred for a request that is in the
 process of loading. Hence, when an instance of load activity occurs
 (e.g. bytes are received from the network for a request), the idle
 interval for a request is reset to 0. If the idle interval ever
 becomes greater than or equal to the timeout interval, the request
 is considered to have timed out. This timeout interval is measured
 in seconds.
 @result The timeout interval of the receiver.

 请求超时时间
 */
 @property (readonly) NSTimeInterval timeoutInterval;

/*!
 @abstract The main document URL associated with this load.
 @discussion This URL is used for the cookie "same domain as main
 document" policy. There may also be other future uses.
 See setMainDocumentURL:
 NOTE: In the current implementation, this value is unused by the
 framework. A fully functional version of this method will be available
 in the future.
 @result The main document URL.
 
 主文档地址 这个地址用来存放缓存
 */
@property (nullable, readonly, copy) NSURL *mainDocumentURL;

/*!
 @abstract Returns the NSURLRequestNetworkServiceType associated with this request.
 @discussion  This will return NSURLNetworkServiceTypeDefault for requests that have
 not explicitly set a networkServiceType (using the setNetworkServiceType method).
 @result The NSURLRequestNetworkServiceType associated with this request.

 获取网络请求的服务类型 枚举如下
 */
@property (readonly) NSURLRequestNetworkServiceType networkServiceType API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

/*!
 @abstract returns whether a connection created with this request is allowed to use
 the built in cellular radios (if present).
 @result YES if the receiver is allowed to use the built in cellular radios to
 satify the request, NO otherwise.
 
 获取是否允许使用服务商蜂窝网络
 */
@property (readonly) BOOL allowsCellularAccess  API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0));

 

     NSURLRequest还有一个NSHTTPURLRequest的类别,这个类别对于我们自定义请求头请求体这些的时候是很重要的,我们先看看这个类别里面有什么:

/*!
 HTTP请求方式  POST GET 等
 */
@property (nullable, readonly, copy) NSString *HTTPMethod;

/*!
 得到一个字典数据,设置的 HTTP请求头的键值数据
 */
@property (nullable, readonly, copy) NSDictionary<NSString *, NSString *> *allHTTPHeaderFields;

/*!
 设置http请求头中的字段值,这个我们待会在看看一些Demo代码和AF的源码比较一下
 */
- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field;

/*!
 请求体
 */
@property (nullable, readonly, copy) NSData *HTTPBody;

/*!
 http请求体的输入流
 */
@property (nullable, readonly, retain) NSInputStream *HTTPBodyStream;

/*!
 设置发送请求时是否发送cookie数据
 */
@property (readonly) BOOL HTTPShouldHandleCookies;

/*!
 设置的请求时是否按顺序收发 默认禁用 在某些服务器中设为YES可以提高网络性能
 */
@property (readonly) BOOL HTTPShouldUsePipelining API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

/*!
  设置http请求头中的字段值
 */
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field;

/*!
 向http请求头中添加一个字段
 */
- (void)addValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

 

      可以看到这个类别全都是关于请求体和请求头的一些设置方法以及属性,既然这里我们说到了这两个东西,我们也说说,下面是我们常见的额请求头设置属性:

      Host: 目标服务器的网络地址

      Accept: 让服务端知道客户端所能接收的数据类型,如text/html

      Content-Type: body中的数据类型,如application/json; charset=UTF-8

      Accept-Language: 客户端的语言环境,如zh-cn

      Accept-Encoding: 客户端支持的数据压缩格式,如gzip

      User-Agent: 客户端的软件环境,我们可以更改该字段为自己客户端的名字,比如QQ music v1.11,比如浏览器Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2

      Connection: keep-alive,该字段是从HTTP 1.1才开始有的,用来告诉服务端这是一个持久连接,“请服务端不要在发出响应后立即断开TCP连接”。关于该字段的更多解释将在后面的HTTP版本简介中展开。

      Content-Length: body的长度,如果body为空则该字段值为0。该字段一般在POST请求中才会有。

 

      再说说请求体,请求体的封装我们用一张图告诉大家:(文顶顶博客转载)

 

 

      要是大家接触过这方面的内容理解上面我们说的请求体和请求头就相对容易一点,但要是完全没有机会接触过,可能就会不知道上面这一段内容说的是什么,其实他们在我们处理文件上传的时候能用到,在以前我关于Telegram写的怎样在它的基础上增加自己得网络请求的时候,在涉及到文件上传这一块有用到过,这里给两篇博客链接,供大家参考学习一下这个请求头和请求体的设置(我记得这个问题我以前面试过的时候有人问过我,可惜...那时候我接触开发不懂这些呀....哈哈)

      iOS上传文件

      iOS开发网络篇—文件的上传

      最后,再说一点上面的关于这个 -- 上传文件的 MIMEType,这个在以前我也有说过,当然这些内容我也会在下面的Demo中体现一下的。

 

NSURLSession


      在说这个之前,我们先看一张图梳理一下他们之间的整体关系(此文的图都是同行博客中收集的,感谢感谢!)

 

 

      接着我们说我们要理解的重点--NSURLSession,下面的内容是按照NSURLSession.h API来写的,你可以对比着来看。先看看NSURLSession:      

/*
  NSURLSession 默认是挂起的状态,要是需要网络请求需要去开启,
  下面这个属性sharedSession就是获取全局的NSURLSession对象。在iPhone的所有app共用一个全局session。
  @property (class, readonly, strong) NSURLSession * sharedSession;
 */

/*
 * Customization of NSURLSession occurs during creation of a new session.
 * If you only need to use the convenience routines with custom
 * configuration options it is not necessary(必要的) to specify(特殊的) a delegate.
 * If you do specify a delegate, the delegate will be retained(保留) until after
 * the delegate has been sent the URLSession:didBecomeInvalidWithError: message.
   代理一直会被保留,直到代理接收到URLSession:didBecomeInvalidWithError:消息
 
   下面两个是利用NSURLSessionConfiguration对象得到NSURLSession的方法,区别在于代理的设置
   + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
   + (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;
*/

/*
 * The sessionDescription property is available for the developer to
 * provide a descriptive label for the session.
 * 该方法是给session添加一个描述信息
 * @property (nullable, copy) NSString *sessionDescription;
 */

/* -finishTasksAndInvalidate returns immediately and existing tasks will be allowed
 * to run to completion.  New tasks may not be created.  The session
 * will continue to make delegate callbacks until URLSession:didBecomeInvalidWithError:
 * has been issued.
 *
 * -finishTasksAndInvalidate and -invalidateAndCancel do not
 * have any effect on the shared session singleton.
 *
 * When invalidating a background session, it is not safe to create another background
 * session with the same identifier until URLSession:didBecomeInvalidWithError: has
 * been issued.
 
   这个方法是任务完成之后调用会释放session
   这里涉及到的是session和代理之间相互的强引用可能会造成内存泄漏的问题,了解一下!
   - (void)finishTasksAndInvalidate;
 */

/* -invalidateAndCancel acts as -finishTasksAndInvalidate, but issues
 * -cancel to all outstanding tasks for this session.  Note task
 * cancellation is subject to the state of the task, and some tasks may
 * have already have completed at the time they are sent -cancel.
 
   这个是取消任务释放session 和前面的任务完成之后是有区别的,上面的注释又给我们解释说让我们注意任务的状态
   可能会给一些结束的任务发送cancel消息
   - (void)invalidateAndCancel;
   NOTE:当对 session invalidate 后,就不能再创建新的 task 了,两个方法的不同之处是,- finishTasksAndInvalidate会等到正在执行的 task 执行完成,调用完所有回调或 delegate 后,释放对 delegate 的强引用,而- invalidateAndCancel方法则是直接取消所有正在执行的 task。
 
 */

/*
 清空所有的 cookie、缓存、证书等,传入的 completionHandler 在上述操作完成后执行。
 empty all cookies, cache and credential stores, removes disk files, issues -flushWithCompletionHandler:. Invokes completionHandler() on the delegate queue if not nil.
 - (void)resetWithCompletionHandler:(void (^)(void))completionHandler;
 */

/*
 将内存中的 cookie、证书等写到硬盘,之后的请求会使用新的 TCP 连接,传入的 completionHandler 在上述操作完成后执行。
 storage to disk 存储到磁盘
 flush storage to disk and clear transient network caches.  Invokes completionHandler() on the delegate queue if not nil.
 - (void)flushWithCompletionHandler:(void (^)(void))completionHandler;
 */

/* 获取 session 中的 task,在获取完 task 列表后会执行传入的 completionHandler 参数,而 task 列表则作为 block 的参数传入。*/
/* invokes completionHandler with outstanding data, upload and download tasks.
   - (void)getTasksWithCompletionHandler:(void (^)(NSArray<NSURLSessionDataTask *> *dataTasks, NSArray<NSURLSessionUploadTask *> *uploadTasks, NSArray<NSURLSessionDownloadTask *> *downloadTasks))completionHandler;
 */

/* invokes completionHandler with all outstanding tasks.
   - (void)getAllTasksWithCompletionHandler:(void (^)(NSArray<__kindof NSURLSessionTask *> *tasks))completionHandler API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));
 */

/*
 * NSURLSessionTask objects are always created in a suspended state (suspend 和 pause 表示暂停 挂起状态) and
 * must be sent the -resume message before they will execute.
 */

//下面的额这些方法都是用来初始化Task的
//当然这个Task就包括dataTask,uploadTask/downloadTask。以及streamTask。。
/* Creates a data task with the given request.  The request may have a body stream.
 - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
 */

/* Creates a data task to retrieve the contents of the given URL.
 - (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;
 */

/* Creates an upload task with the given request.  The body of the request will be created from the file referenced by fileURL
 - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
 */

/* Creates an upload task with the given request.  The body of the request is provided from the bodyData.
 - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;
 */

/* Creates an upload task with the given request.  The previously set body stream of the request (if any) is ignored and the URLSession:task:needNewBodyStream: delegate will be called when the body payload is required.
 - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;
 */

/* Creates a download task with the given request.
 - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
 */

/* Creates a download task to download the contents of the given URL.
 - (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
 */

/* Creates a download task with the resume data.  If the download cannot be successfully resumed, URLSession:task:didCompleteWithError: will be called.
   - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
 */

/* Creates a bidirectional stream (双向) task to a given host and port.
 - (NSURLSessionStreamTask *)streamTaskWithHostName:(NSString *)hostname port:(NSInteger)port API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
 */

/* Creates a bidirectional stream task with an NSNetService to identify the endpoint.
 * The NSNetService will be resolved before any IO completes.
 - (NSURLSessionStreamTask *)streamTaskWithNetService:(NSNetService *)service API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
 */

 

      在API接下来中应该是NSURLSessionAsynchronousConvenience这个NSURLSession的类别,但这个比较简单,它只是在上面我们提到的Task初始化的基础上加上了一个completionHandler的block,也就是一个初始化完成的block,关于这我们也就不再多说了。

      接着往下面看,再往下就是NSURLSessionTask这个比较核心的类了,后面我们说的四个类(data/upload/download/stream)Task ,其中data、download、stream是继承自我们要说的NSURLSessionTask这个核心。 而我们的上传upload是继承自data,这个也不难理解!这三个类封装了现代应用程序的三个基本网络任务:获取数据,比如JSON/XML,以及上传和下载文件。下面是我们对这些API的理解:

      我们也是用过这张看看Task之间的关系:

      嗯,就从最基本的NSURLSessionTask的API开始说起:

/*
@interface NSURLSessionTask : NSObject <NSCopying, NSProgressReporting>
@property (readonly)                 NSUInteger    taskIdentifier;    an identifier for this task, assigned by and unique to the owning session
@property (nullable, readonly, copy) NSURLRequest  *originalRequest;  may be nil if this is a stream task
@property (nullable, readonly, copy) NSURLRequest  *currentRequest;   may differ from originalRequest due to http server redirection
// 服务器对当前活动请求的响应
@property (nullable, readonly, copy) NSURLResponse *response;         may be nil if no response has been received

 * NSProgress object which represents the task progress.
 * It can be used for task progress tracking.  进度
 @property (readonly, strong) NSProgress *progress API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));

 网络负载应该开始的最早日期
 对于从后台NSURLSession实例创建的任务,此属性表示网络负载不应该在此日期之前开始。 设置此属性并不能保证加载将从指定的日期开始,而只是它不会马上开始。 如果未指定,则不使用启动延迟。
 此属性对从非后台会话创建的任务没有影响。
 * Start the network load for this task no earlier than the specified date. If
 * not specified, no start delay is used.
 * 只适用于后台NSURLSession
 * Only applies to tasks created from background NSURLSession instances; has no
 * effect for tasks created from other session types.
 @property (nullable, copy) NSDate * earliestBeginDate API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
 
 下面这两个属性其实是比较重要的,两个解释分贝如下:
 1、客户期望发送的字节数的期待上限。
 为此属性设置的值应考虑HTTP头和正文数据或正文流的大小。如果未指定值,则系统将使用NSURLSessionTransferSizeUnknown。该属性由系统用来优化URL会话任务的调度。强烈建议开发人员尽可能提供近似的上限或确切的字节数,而不是接受默认值。
 2、客户期望接收的字节数的期待上限。
 为此属性设置的值应考虑HTTP响应头和响应主体的大小。如果未指定值,则系统将使用NSURLSessionTransferSizeUnknown。该属性由系统用来优化URL会话任务的调度。强烈建议开发人员尽可能提供近似的上限或确切的字节数,而不是接受默认值。
 * The number of bytes that the client expects (a best-guess upper-bound) will
 * be sent and received by this task. These values are used by system scheduling
 * policy. If unspecified, NSURLSessionTransferSizeUnknown is used.
 
 @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));

 * Byte count properties may be zero if no body is expected,
 * or NSURLSessionTransferSizeUnknown if it is not possible 
 * to know how many bytes will be transferred.

// 实际发送和接受的字节
number of body bytes already received
@property (readonly) int64_t countOfBytesReceived;
number of body bytes already sent
@property (readonly) int64_t countOfBytesSent;
 
//预计发生的数据,和 Content-Length of the HTTP request 有关
number of body bytes we expect to send, derived from the Content-Length of the HTTP request
@property (readonly) int64_t countOfBytesExpectedToSend;
//预计接收,通常来自HTTP响应的内容长度标题。
number of byte bytes we expect to receive, usually derived from the Content-Length header of an HTTP response.
@property (readonly) int64_t countOfBytesExpectedToReceive;

该任务描述
 * The taskDescription property is available for the developer to
 * provide a descriptive label for the task.
@property (nullable, copy) NSString *taskDescription;

 -cancel returns immediately, but marks a task as being canceled.
 * The task will signal -URLSession:task:didCompleteWithError: with an
 * error value of { NSURLErrorDomain, NSURLErrorCancelled }.  In some 
 * cases, the task may signal other work before it acknowledges the 
 * cancelation.  -cancel may be sent to a task that has been suspended.
 将任务标记为取消
- (void)cancel;

 当前任务的状态
 * The current state of the task within the session.
 @property (readonly) NSURLSessionTaskState state;

 错误
 * The error, if any, delivered via -URLSession:task:didCompleteWithError:
 * This property will be nil in the event that no error occured.
 @property (nullable, readonly, copy) NSError *error;

 暂停/恢复
 - (void)suspend;
 - (void)resume;

 任务优先级
 @property float priority API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

@end
 
下面就是前面说的优先级的值
FOUNDATION_EXPORT const float NSURLSessionTaskPriorityDefault API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
FOUNDATION_EXPORT const float NSURLSessionTaskPriorityLow API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
FOUNDATION_EXPORT const float NSURLSessionTaskPriorityHigh API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

 

      上面我们说了这个NSURLSessionTask还要三个子类,在API中前面的两个子类我就没有什么还能说的了,因为都包含在了NSURLSessionTask中,唯一有一个需要我们说一下的,就是在NSURLSessionDownloadTask中有一个方法是父类中没有的,我们看看对这个方法的理解:

 
 * 取消下载 但取消的下载资源我们还能继续下载(恢复数据以供以后使用)。只有满足以下条件时才能恢复下载:
 1、请求资源后,资源并未发生变化
 2、该任务是一个HTTP或HTTPS GET请求
 3、服务器在其响应中提供ETag或Last-Modified标头(或两者都有)
 4、服务器支持字节范围请求
 5、系统为响应磁盘空间压力而未删除临时文件
 
 * Cancel the download (and calls the superclass -cancel).  If
 * conditions will allow for resuming the download in the future, the
 * callback will be called with an opaque data blob, which may be used
 * with -downloadTaskWithResumeData: to attempt to resume the download.
 * If resume data cannot be created, the completion handler will be
 * called with nil resumeData.
 
- (void)cancelByProducingResumeData:(void (^)(NSData * _Nullable resumeData))completionHandler;

 

      其实在看了上面的API解释之后,大家会发现有一个我们还没说,那就是NSURLSessionStreamTask,这个里面包含的内容比较多,并且和它包含了许多父类没有的方法,在日常开发中我暂时是没有遇到过这一块的东西,但还是通过查找资料,把这一块的API也相应的熟悉一下,方便以后我们查找使用:

@interface NSURLSessionStreamTask : NSURLSessionTask
 
 异步地从流中读取若干个字节,并在完成时调用处理程序。
 读取minBytes或最多maxBytes字节,并在会话委托队列中调用数据或错误的完成处理程序。如果发生错误,任何未完成的读取也将失败,并且新的读取请求将立即出错。
 * Read minBytes, or at most maxBytes bytes and invoke the completion
 * handler on the sessions delegate queue with the data or an error.
 * If an error occurs(发生), any outstanding(未完成) reads will also fail, and new
 * read requests will error out immediately.
 
 - (void)readDataOfMinLength:(NSUInteger)minBytes maxLength:(NSUInteger)maxBytes timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSData * _Nullable data, BOOL atEOF, NSError * _Nullable error))completionHandler;
 
 将指定的数据异步写入流,并在完成时调用处理程序
 * Write the data completely to the underlying socket.  If all the
 * bytes have not been written by the timeout, a timeout error will
 * occur.  Note that invocation(调用) of the completion handler does not
 * guarantee (确保) that the remote side has received all the bytes, only
 * that they have been written to the kernel.
 - (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSError * _Nullable error))completionHandler;
 
 获取流
 完成所有已排队的读取和写入,然后调用URLSession:streamTask:didBecomeInputStream:outputStream:delegate消息。
 收到该消息时,任务对象被视为已完成,并且不会再收到任何委托消息。
 * -captureStreams completes any already enqueued(队列) reads
 * and writes, and then invokes the
 * URLSession:streamTask:didBecomeInputStream:outputStream: delegate
 * message. When that message is received, the task object is
 * considered completed and will not receive any more delegate
 * messages.
 - (void)captureStreams;

 
 排队请求以关闭底层Socket的写入结束。 所有未完成的IO将在Socket的写入端关闭之前完成。
 但是,服务器可能会继续将字节写回到客户端,因此最佳做法是从服务器继续读取,直到你收到EOF。
 * Enqueue a request to close the write end of the underlying socket.
 * All outstanding IO will complete before the write side of the
 * socket is closed.  The server, however, may continue to write bytes
 * back to the client, so best practice is to continue reading from
 * the server until you receive EOF.
 - (void)closeWrite;

 
 排队请求以关闭底层Socket的读取端。 所有未完成的IO将在读取端关闭之前完成。 你可以继续写入服务器。
 * Enqueue a request to close the read side of the underlying socket.
 * All outstanding IO will complete before the read side is closed.
 * You may continue writing to the server.
 - (void)closeRead;

 开始加密握手。 握手在所有待处理IO完成后开始。 TLS认证回调被发送到会话-URLSession:task:didReceiveChallenge:completionHandler:
 * Begin encrypted handshake.  The hanshake begins after all pending
 * IO has completed.  TLS authentication callbacks are sent to the
 * session's -URLSession:task:didReceiveChallenge:completionHandler:
 - (void)startSecureConnection;

 完成所有挂起的安全IO后,干净地关闭安全连接。
 * Cleanly close a secure connection after all pending secure IO has
 * completed.

 - (void)stopSecureConnection;

 

      哇哇哇......看了看自己对API注释的内容,发现还有差不多一半的内容没有说,可这篇幅会很长呀.......

      接下来按照API的内容我们要说的还有下面这个几个点:

      1、NSURLSessionTaskDelegate

      2、NSURLSessionDataDelegate

      3、NSURLSessionDownloadDelegate

      4、NSURLSessionStreamDelegate

      5、NSURLSessionTaskTransactionMetrics

      6、NSURLSessionTaskMetrics

      O__O "…  还是在起一篇总结吧,在接下来的文章中就会总结上面说的这六个点的API,以及我们的Demo,当然Demo还是得提前发出来的当你看到这篇文章的时候相信第二篇也已经是写好了,只等发出... 

       

      Demo 连接点击这里   (和以前的我们写的关于AVFoundation)的Demo是在一起的,这部分的demo在NSURLSession文件夹下面,大家自己找找哈.

      NSURLSession 所有的都在这里(二)

 

      参考文章:

             1、深入了解NSURLSession

             2、网络请求之NSURLSession(api篇)

 

posted @ 2018-05-09 16:22  MrRisingSun  阅读(3444)  评论(1编辑  收藏  举报