URL 介绍
URL的组成:
一般情况是: 协议(scheme)://主机名(host):端口(port)/服务器上资源的路径(path)?参数
例子:http://100.0.0.0:8080/xxx?id=3
通用格式:协议://用户名(user):密码(password)@主机名:端口/服务器上资源的路径?参数#片段(fragment)
例子:ftp://joe:joepasswd@ftp.prep.edu/pub/name/xxx?id=3#name
协议(scheme):
httphttpsftp等等
用户名和密码:很多服务器都要求输入用户名和密码才会允许用户访问数据,如FTP服务器。
主机名(host):://后边的域名或者 ip。例如:htouhui.comor100.0.0.0
端口(port)::后边的8080 路径(path):端口后边的第一个/开始到?结束,路径说明了资源位于服务器的什么地方 参数:?后边#前边 例如id=3片段(fragment):#后边的,例如name
NSURLRequest
NSUrlRequest 是封装了2个必要内容:URL和扩展
URL:请求头,请求体,输入流,请求方法,超时时间等等
扩展:协议(Http https ftp 等等的成熟协议和自定义协议),缓存等等
[注]:NSURLRequest继承NSSecureCoding协议,NSSecureCoding的前身是NSCoding,NSSecureCoding更加安全,主要目的是:继承这个写协议的类可以和NSData互相转换。
NSURLCache
缓存
//缓存策略:
NSURLRequestUseProtocolCachePolicy = 0, //默认的缓存策略(取决于协议)
NSURLRequestReloadIgnoringLocalCacheData = 1, // 忽略缓存,重新请求
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
NSURLRequestReturnCacheDataElseLoad = 2, // 有缓存就用缓存,没有缓存就重新请求
NSURLRequestReturnCacheDataDontLoad = 3, // 有缓存就用缓存,没有缓存就不发请求,当做请求出错处理(用于离线模式)
NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
NSHTTPCookieStorage
管理cookie全局缓存池
一般系统默认去管理这个对象,开发人员也可以管理(加载的时机由系统控制)
NSURLCredentialStorage
管理身份验证信息
2个子类
NSInternetPassword: 用户名和密码验证
NSClientCertificate: 证书验证
NSURLConnection
iOS 2 的时候推出的网络接口(iOS 9废除),接口比较少,实现了简单的功能,暂停,断点续传,监听进度等等的功能,自能开发人员自己去实现。
由上图我们可以知道NSURLConnection发送网络请求的工作流程:
NSURLRequest对象被传递给NSURLConnection对象.NSURLConnection在NSURLCache里边找,如果有直接返回NSURLResponse.- 如果没有,拿到
NSHTTPCookieStorage里的cookie 和NSURLCredentialStorage里的身份验证信息,发送网络请求 - 在
NSURLProtocol的代理里边得到NSURLResponse
NSURLSessionConfiguration
网络请求配置,包括会话类型,缓存,超时时间,缓存,cookie,认证配置
//会话类型为下边的3种
//默认会话类型,能够进行磁盘缓存
//他们使用永久性的基于磁盘的缓存并将凭证存储在用户的钥匙串
@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;
//临时会话类型,不进行任何的磁盘缓存
//所有的缓存,凭证存储等都保存在RAM中并与会话绑定。因此,当您的应用程序使会话失效时,它们会自动清除
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;
//后台类型,用于后台下载上传
//与默认会话类似,不同之处在于单独的进程处理所有数据传输
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier;
//后台会话配置的标识符
@property (nullable, readonly, copy) NSString *identifier;
//超时时间
@property NSTimeInterval timeoutIntervalForRequest;
//ServiceType
@property NSURLRequestNetworkServiceType networkServiceType;
//是否使用流量
@property BOOL allowsCellularAccess;
//cookie 配置
@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy;
@property (nullable, retain) NSHTTPCookieStorage *HTTPCookieStorage;
//缓存配置
@property NSURLRequestCachePolicy requestCachePolicy;
@property (nullable, retain) NSURLCache *URLCache;
//认证配置
@property (nullable, retain) NSURLCredentialStorage *URLCredentialStorage;
NSURLSessionTask
NSURLSessionTask 有2个子类,继承关系如下图
NSURLSessionTask是一个抽象类,如果要使用那么只能使用它的子类。
NSURLSessionDataTask可以用来处理一般的网络请求,如 GET | POST 请求等。
NSURLSessionDataTask有一个子类为 NSURLSessionUploadTask,用于处理上传请求的时候有优势。
NSURLSessionDownloadTask主要用于处理下载请求,有很大的优势。
NSURLSession
NSURLConnection 的升级版本,功能比前者强大太多,也支持Http的更高的版本,传输速度更快。
@interface NSURLSession : NSObject
/* sharedSession属性表示使用当前的全局的NSURLCache,
NSHTTPCookieStorage 和 NSURLCredentialStorage对象。
*/
@property (class, readonly, strong) NSURLSession *sharedSession;
/*
* 构建方法
*/
+ (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;
/*
* 可以提供对session 的标签描述
*/
@property (nullable, copy) NSString *sessionDescription;
/* 立即返回,现有任务将被允许运行完成。 新任务可能无法创建。
会话将继续进行代理的回调,直到发布URLSession:didBecomeInvalidWithError:为止。
finishTasksAndInvalidate 和 invalidateAndCancel 对共享会话单例没有任何影响.
当使后台会话无效时,在URLSession:didBecomeInvalidWithError:已经发布之前,使用相同的标识符创建另一个后台会话是不安全的。
*/
- (void)finishTasksAndInvalidate;
/* 充当 finishTasksAndInvalidate,但是会针对此会话的所有未完成任务执行取消 cancel。
*/
- (void)invalidateAndCancel;
- (void)resetWithCompletionHandler:(void (^)(void))completionHandler; /* empty all cookies, cache and credential stores, removes disk files, issues -flushWithCompletionHandler:. Invokes completionHandler() on the delegate queue if not nil. */
- (void)flushWithCompletionHandler:(void (^)(void))completionHandler; /* flush storage to disk and clear transient network caches. Invokes completionHandler() on the delegate queue if not nil. */
- (void)getTasksWithCompletionHandler:(void (^)(NSArray<NSURLSessionDataTask *> *dataTasks, NSArray<NSURLSessionUploadTask *> *uploadTasks, NSArray<NSURLSessionDownloadTask *> *downloadTasks))completionHandler; /* invokes completionHandler with outstanding data, upload and download tasks. */
- (void)getAllTasksWithCompletionHandler:(void (^)(NSArray<__kindof NSURLSessionTask *> *tasks))completionHandler API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0)); /* invokes completionHandler with all outstanding tasks. */
/*
* NSURLSessionTask objects are always created in a suspended state and
* must be sent the -resume message before they will execute.
*/
// NSURLSessionTask对象必须在暂停状态下创建,必须发送- resume消息才执行。
/* 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. */
// 创建数据任务以检索给定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 */
// 根据给定的请求创建一个给定的上传任务,请求体根据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. */
// 根据给定的请求,创建一个上传任务,请求体根据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. */
// 根据给定的请求创建上传任务,忽略以前请求的体流设置,当需要加载体的时候,
// 将会调用URLSession:task:needNewBodyStream: 代理方法。
- (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. */
// 创建下载任务,下载给定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. */
// 根据resume data创建一个下载任务,如果下载不能成功开始,那么会调用URLSession:task:didCompleteWithError:
- (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.
*/
// 使用NSNetService识别端点以创建双向流任务。
// NSNetService将在任何IO完成之后解决
- (NSURLSessionStreamTask *)streamTaskWithNetService:(NSNetService *)service API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
分类 NSURLSessionAsynchronousConvenience
// NSURLSession便捷例程将结果传递给完成处理程序块。 这些便利例程不适用于配置为后台会话的NSURLSessions。
// 任务对象总是在挂起状态创建,并且必须在执行之前发送-resume消息。
@interface NSURLSession (NSURLSessionAsynchronousConvenience)
/*
* data task convenience methods. These methods create tasks that
* bypass the normal delegate calls for response and data delivery,
* and provide a simple cancelable asynchronous interface to receiving
* data. Errors will be returned in the NSURLErrorDomain,
* see <Foundation/NSURLError.h>. The delegate, if any, will still be
* called for authentication challenges.
*/
// 数据任务的便利方法。 这些方法创建绕过普通代理调用进行响应和数据传递的任务,
// 并提供一个简单的可取消异步接口来接收数据。 错误将在NSURLErrorDomain中返回,
// 请参阅<Foundation / NSURLError.h>。 代理(如果有的话)仍将被要求认证挑战。
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
/*
* upload convenience method.
*/
// 上传任务便利化方法
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(nullable NSData *)bodyData completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
/*
* download task convenience methods. When a download successfully
* completes, the NSURL will point to a file that must be read or
* copied during the invocation of the completion routine. The file
* will be removed automatically.
*/
// 下载任务便利化方法,当成功下载完成时,URL指向一个文件,
// 这个文件必须在完成调用中进行读和赋值,文件将被自动移除。
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
@end
那么怎么理解这3个类呢?
URLSession是负责发送和接收请求的关键对象, URLSessionConfiguration 是URLSession的配置参数,可以通过URLSessionConfiguration来创建URLSession;而URLSessionTask 是一次任务(会话),他是URLSession的具体执行者。下图可以看到:
NSURLSession 和 NSURLConnection 的区别和联系
联系
- 都使用
NSURLRequestURLCacheNSHTTPCookieStorageNSURLCredentialStorage这些基本类来处理。 - 底层都是是使用C写的一套API(这一条是我在什么地方看到过,写的时候没有找到)
NSURLSession 优势
- 直接支持暂停,恢复,取消,重新开始(没有使用NSOperation子类的必要) 。
- 支持后台上传和下载
- 每个
NSURLSession都可以单独配置URLSessionConfiguration - 支持 http2.0 协议
- 在处理下载任务的时候可以直接把数据下载到磁盘
- 同一个 session 发送多个请求,只需要建立一次连接(复用了TCP)
- 提供了全局的 session 并且可以统一配置,使用更加方便
- 载的时候是多线程异步处理,效率更高
不同
- NSURLConnection 是 iOS2.0后推出的 NSURLSession 是iOS7.0后推出的,用于代替 NSURLConnection.
- 下载任务方式
NSURLConnection使用异步回调,先将数据下载到内存,等下载完毕后,再写入沙盒.如果文件很大,会导致内存暴涨; 并且,使用异步回调无法监听下载进度.所以使用NSURLConnection下载的时候,使用代理回调监听下载进度,并且下载过程中要手动管理内存(导致内存暴涨),使用起来比较麻烦.而使用NSURLSession的时候,block和代理可以同时起作用,并且可以直接从文件系统上传、下载,不会出现内存暴涨的情况. 下载文件的时候,默认会将文件下载到沙盒的 tmp文件夹中,不会占多少用内存. 但是在下载完成后,会删除文件,所以要在下载完成或者其他需要的地方,增加保存文件的代码. - 请求方式的控制
NSURLConnection实例化对象,实例化开始,默认请求就发送(同步发送),不需要调用start方法。而cancel可以停止请求的发送,停止后不能继续访问,需要创建新的请求。NSURLSession有三个控制请求的方法,取消(cancel),暂停(suspend),继续(resume),暂停后可以通过继续恢复当前的请求任务。 - 断点续传实现方式
NSURLConnection进行断点下载,通过设置访问请求的HTTPHeaderField的Range属性,开启运行循环,NSURLConnection的代理方法作为运行循环的事件源,接收到下载数据时代理方法就会持续调用,并使用NSOutputStream(或者通过文件指针)管道流进行数据保存。NSURLSession进行断点下载,当暂停下载任务后,如果downloadTask(下载任务)为非空,调用cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler这个方法,这个方法接收一个参数,完成处理代码块,这个代码块有一个NSData参数resumeData,如果resumeData非空,我们就保存这个对象到视图控制器的resumeData属性中。在点击再次下载时,通过调用[ [self.session downloadTaskWithResumeData: self.resumeData]resume]方法进行继续下载操作。经过以上比较可以发现,使用NSURLSession进行断点下载更加便捷。 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,数据传输才会继续。
参考文章:
www.jianshu.com/p/2d4d1d7df…
www.cnblogs.com/1018475062q…
cloud.tencent.com/developer/a…
www.jianshu.com/p/877dec053…