网络资源加载方式(一)

URLLoading System( 网络资源加载)

Foundation框架中提供了资源网络请求部分的基本组件,通过指定-URL(资源路径)和TransformProtocol(传输协议),通过stream流实现数据的传输。常见的传输协议主要有以下几种:

*File Transfer Protocol (ftp://) 文件传输协议:常用作文件传输协议,公司内部和局网内常使用。

*Hypertext Transfer Protocol (http://)超文本传输协议: 常用于浏览器中网络请求

*Hypertext Transfer Protocol with encryption (https://)加密的超文本传输协议,就是在http的基础上增加了C/S(服务器与客户端)之间的认证,

  • Local file URLs (file:///),本地资源传输协议,按照协议规定的格式从本地加载资源,其后指定的就是资源在本地的路径,大家有没有主意到这里有三条斜杠,因为所有的协议必须以 ://+ 主机地址或域名:端口号 +/文件资源路径或者是查询语句。 此处是加载本地文件,所以中间的主机域名和端口号省略了就变成:///。

  • Data URLs (data://) 数据传输协议。

当然除此之外你还可以定义自己的协议,比如苹果的 sms:// 短信协议, prompt:// ,

  • 例如当我门要与HTML5做交互的时候,可以通过定义我门自己的协议头 ourselfprotocol://+你需要拦截信息。 不熟悉的朋友请看UIWebView头文件的代理方法。 通过截获协议头的scheme,我们就能快速的定位那些是需要我门拦截分析的URL了,当然你也可以通过字符串进行分割。

+URL加载系统包括类加载URL以及一些重要的助手类,使用这些URL加载类修改他们的行为。助手类主要分为五类:协议支持,认证和证书,cookie存储、配置管理和缓存管理。Foundation中主要提供了如下几个类用于网络资源的加载.包括目前的很多主流框架如SDWebImage,AFNetWroking,都依赖这些类。主要常用的还是NSURLConnection,NSURLSession,NSURL,NSURLRequest.

资源加载协议类NSURLProtocol

 *从名字上很容易想到它是一个定义资源加载的协议,其实不然. 它属于一个抽象的类,定义了一些基本的方法,主要是机遇网络请求资源加载的。通常使用它的子类进行扩展,当使用NSURLSession和NSURLConnection进行网络资源加载的时候,通常会去访问NSURLClinetProtocol,即询问请求方是否能够处理这个请求,如果返回能则使用我门自定的子类进行网络资源加载,如果不能则使用系统默认的方式进行资源加载
//这是一个NSURLProtoclClient的对象,它就像一个钩子 一样,如果我们如果在NSURLLoadingSystem询问NSURlProtocol 的canInitWithRequest 方法时候,回答YES,则需要我们自己定义类去处理网络请求,这个时候NSURLProtocolClient实例就是专门来帮我们处理网络请求资源的回调的。之所以系统定义到这个类的属性里,是为了我门在创建NSURLProtocol子类的时候,通过子类能够狠方便的调用 NSURLProtocolClient的实例去处理网路资源的加载。
@property (nullable, readonly, retain) idclient;  
//一个请求对象的实例对象,将我门访问的URL资源路径,请求头中的一些参数进行了统一的封装,如 accept type,Content-Type,文件的编码格式,压缩方式,是否保持心跳连接,是否适用Cookie,lastModify time,服务器名称,版本号,协议版本号,请求方式GET,POST,请求资源的长度,常用的就只有accetpt type,Content-Type,
@property (readonly, copy) NSURLRequest *request;  
//这个属性从字面意思都能看得出来,就是缓存request 的响应数据的,方便下次系统调用的时候直接获取
@property (nullable, readonly, copy) NSCachedURLResponse *cachedResponse;
//这个属性用到的比较多,系统在请求网络资源或从定向的时候都会来询问这个方法,如果回答是,则表示 使用用户自定义的protocol来处理网络资源的加载,如果我门需要使用离线加载,则需要将此方法进行改写。
+ (BOOL)canInitWithRequest:(NSURLRequest *)request; 
//这个方法相当与事给我门需要进行请求的Request对象的headerFields进行重新设置,我门可以自定一请求头,这样我门可以通过request headerFields中的某些特定的属性来过滤我门不需要处理的Request,让她们直接采用NSURLLoadingSystem系统的方式进行网络资源的加载。我门可以通过改写系统这个方法,设置它的通用的请求头, 如 appKey :xxxx, userAgent: xxxx,version: ios Mobile
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;
//缓存专用API,判断本地缓存中NSURLRequest对象和我门需要请求的NSURLRequest对象是否相同,如果是相通的 。。。那么。。。。
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b;
//开始进行资源加载,这个方法执行的前提是当我门实现了
- (void)startLoading;
//停止加载
- (void)stopLoading; 

+(BOOL)CanInitWithRequet方法并返回YES后,并且使用+ (BOOL)registerClass:(Class)protocolClass注册我门自定义的NSURLProtocol子类;才会执行此方法,这就是前面说到的我门自己实现网络资源的加载。

//下面几个APi主要是对我门需要处理的NSURLRequest对象进行处理,标记那些已经是请求过的,那些是没有请求过的。通过KVO的方式给它的headerFIelders添加一个参数进行判定。 
+ (nullable id)propertyForKey:(NSString *)key inRequest:(NSURLRequest *)request;
+ (void)setProperty:(id)value forKey:(NSString *)key inRequest:(NSMutableURLRequest *)request;

+ (void)removePropertyForKey:(NSString *)key inRequest:(NSMutableURLRequest *)request;

+ (BOOL)registerClass:(Class)protocolClass;

主要是为了配合我门在完成自定义的资源加载过程中的请求,我门只需要在实现的NSURLSession和NSURLConnection的代理方法中通过钩子来实现这些方法就行了,将 URL资源加载成功,加载失败,加载完成,重定向进行重。这样就保证的在我门自定义处理网络资源加载后,最后又将结果移交给了系统URLLoadingSystem处理。

NSURLProtocol子类的实例->URLLoadingSystem-》询问NSURLProtocol canInitWithRequest-(是)》startLoading->调用NSURLSession/NSURLConnection进行网络资源请求-》在请求完成的代理方法中实现NSURLClientProtocol请求处理。-》注销NSURLProtocol子类实例。总的来说系统自动进行URL资源加载->切换手动资源加载-》加载结束切换系统进行URL资源加载。而在手动进行资源加载过程中,这期间的request,response,redirectRequest,cache,data,error,所有的这些时间都由我门自己定义。 你只需要在子类重写的canInitWithRequest方法中进行拦截我门需要处理的请求进行处理就可以了,甚至还可以对我门项目需要离线加载的页面做一个专门的配置文件表,在此方法类的每次请求的URLRequest对象做一个判定,然后再进行处理。

//下面为NSURLClient的实现方法,
- (void)URLProtocol:(NSURLProtocol *)protocol wasRedirectedToRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;


```objective-c 
//截获重定向的URL请求头,确定是否响应。
- (void)URLProtocol:(NSURLProtocol *)protocol cachedResponseIsValid:(NSCachedURLResponse *)cachedResponse;
//缓存是否有效
- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveResponse:(NSURLResponse *)response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy;
//设置Request的缓存策略,由于我门是自定义子类,如果你需要完成自定义的离线缓存,那么此方法类需要适用设置为NSURLCacheStoreagePolicy为NO。
- (void)URLProtocol:(NSURLProtocol *)protocol didLoadData:(NSData *)data;
//此方法与NSURLSession didReceiveData 或者NSURLConnection didReceviveData一起使用,将接收到的数据返回给NSURLLoadingSystem(系统资源加载系统).这样才不会影响我门在其他的类文件里调用网络请求方法获取数据。
- (void)URLProtocolDidFinishLoading:(NSURLProtocol *)protocol;
- (void)URLProtocol:(NSURLProtocol *)protocol didFailWithError:(NSError *)error;
- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;

*自己对请求的授权挑战进行处理, 因为我门自定义子类,主要是做离线缓存,或者设定Request请求头的一些规则,以及重定向之类的. 此处你也可以为指定的一些https的请求做一些特殊的处理。

*首先需要拿到challenge的保护空间,获取到服务器的受信任对象,serverTrust,其实就是一个证书凭证,不过现在通过stream流传输过来被系统封装成了一对象。 如果这个对象是

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

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,169评论 11 349
  • iOS网络编程读书笔记 Facade Tester客户端门面模式的实例(被动版本化) 被动版本化,所以硬编码URL...
    melouverrr阅读 1,598评论 3 7
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,389评论 25 707
  • 说一件事 前几天的 下雨。 从新华书店回学校的2路公交车上,忘记哪一站了。 上来一个头发花白的老爷爷,个子很高很高...
    蜻蜓队长的pen阅读 598评论 0 0