通过重写NSURLProtocol实现UIWebView的数据缓存
2016-08-16 19:15
417 查看
由于公司项目是混合开发,基本上全部是通过UIWebView加载的,虽然这样减轻了客户端的工作量,但是,不可避免会遇到网络差,服务器不稳定等的情况,在这种情况下,webView的加载效果就很差了,严重影响客户体验,于是产品经理要求研究客户端的优化、缓存问题。网上是找了一个NSURLProtocol的缓存的思路的,但是到今天实际上手操作的时候就遇到问题了。今天下午就好好研究了一下,终于把问题搞定了。下面开始正文:
一、NSURLProtocol 简介
其实网上关于NSURLProtocol的介绍已经很好很详细了,我就不做过多介绍了,说最主要的一点,你可以通过继承NSURLProtocol,自定义一个子类,然后可以轻松的重新定义苹果的URL加载系统 (URL Loading System)的行为。通过拦截,可以实现各种操作
二、实现的主要步骤
首先,要在AppDelegate.m的- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions 里面进行注册
[NSURLProtocol registerClass:[MyConnectionURLProtocol class]];
然后,重写NSURLProtocol的方法
+ (BOOL)canInitWithRequest:(NSURLRequest *)request;
每个请求都会进入这个方法,返回YES表示接管系统请求,自己进行相关操作,返回NO,表示,默认系统的请求。我们可以在这个方法里面判断自己需要做处理的连接,可以根据实现webView缓存,判断要加载的资源在本地是否存在,如果存在,接管系统请求,加载本地资源
这是相应的判断。
当上面的操作返回为YES的时候,才会继续下面的操作。
- (void)startLoading重写该方法,需要在该方法中发起一个请求,对于NSURLConnection来说,就是创建一个NSURLConnection,对于NSURLSession,就是发起一个NSURLSessionTask,在这里可以进行相关的操作,加载本地资源
重写- (void)stopLoading该方法,需要停止响应的请求
此外,还要重写+ (NSURLRequest )canonicalRequestForRequest:(NSURLRequest )request该方法,可以增加或修改请求头等操作,主要是改变request的操作
三、实现NSURLConnectionDataDelegate协议代理方
以上操作就可以实现UIWebView的缓存,谢谢观看
一、NSURLProtocol 简介
其实网上关于NSURLProtocol的介绍已经很好很详细了,我就不做过多介绍了,说最主要的一点,你可以通过继承NSURLProtocol,自定义一个子类,然后可以轻松的重新定义苹果的URL加载系统 (URL Loading System)的行为。通过拦截,可以实现各种操作
二、实现的主要步骤
首先,要在AppDelegate.m的- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions 里面进行注册
[NSURLProtocol registerClass:[MyConnectionURLProtocol class]];
然后,重写NSURLProtocol的方法
+ (BOOL)canInitWithRequest:(NSURLRequest *)request;
每个请求都会进入这个方法,返回YES表示接管系统请求,自己进行相关操作,返回NO,表示,默认系统的请求。我们可以在这个方法里面判断自己需要做处理的连接,可以根据实现webView缓存,判断要加载的资源在本地是否存在,如果存在,接管系统请求,加载本地资源
+ (BOOL)canInitWithRequest:(NSURLRequest *)request { /* 防止无限循环,因为一个请求在被拦截处理过程中,也会发起一个请求,这样又会走到这里,如果不进行处理,就会造成无限循环 */ if ([NSURLProtocol propertyForKey:protocolKey inRequest:request]) { return NO; } NSString * url = request.URL.absoluteString; // 如果url已http或https,开头,则进行拦截处理,否则不处理 if ([url hasPrefix:@"http"] || [url hasPrefix:@"https"]) { //判断要加载的资源本地是否存在 if ([MyConnectionURLProtocol localResourceIsExistWith:request]) { return YES; } else { return NO; } } return NO; }
这是相应的判断。
当上面的操作返回为YES的时候,才会继续下面的操作。
- (void)startLoading重写该方法,需要在该方法中发起一个请求,对于NSURLConnection来说,就是创建一个NSURLConnection,对于NSURLSession,就是发起一个NSURLSessionTask,在这里可以进行相关的操作,加载本地资源
NSMutableURLRequest * request = [self.request mutableCopy]; // 表示该请求已经被处理,防止无限循环 [NSURLProtocol setProperty:@(YES) forKey:protocolKey inRequest:request]; NSLog(@"URL %@",request.URL.absoluteString); NSString *str = request.URL.path; NSString *Regex = nil; if ([str.pathExtension isEqualToString:@"js"]) { Regex = [MyConnectionURLProtocol addLocalFileReturnRex:@"js"]; }else if ([str.pathExtension isEqualToString:@"css"]) { Regex = [MyConnectionURLProtocol addLocalFileReturnRex:@"css"]; }else if ([str.pathExtension isEqualToString:@"jpg"]||[str.pathExtension isEqualToString:@"png"]) { Regex = [MyConnectionURLProtocol addLocalFileReturnRex:@"img"]; } [MyConnectionURLProtocol rexString:str rex:Regex success:^(NSString *matchStr) { NSArray *fileArr = [matchStr componentsSeparatedByString:@"."]; [self addFiledToClient:matchStr MIMEType:fileArr.lastObject]; } faild:^{ self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; }];
重写- (void)stopLoading该方法,需要停止响应的请求
- (void)stopLoading { [self.connection cancel]; }
此外,还要重写+ (NSURLRequest )canonicalRequestForRequest:(NSURLRequest )request该方法,可以增加或修改请求头等操作,主要是改变request的操作
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { // 修改了请求的头部信息 NSMutableURLRequest *mutableReqeust = [request mutableCopy]; mutableReqeust = [self redirectHostInRequset:mutableReqeust]; return mutableReqeust; }
三、实现NSURLConnectionDataDelegate协议代理方
#pragma mark - NSURLConnectionDelegate - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [self.client URLProtocol:self didLoadData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [self.client URLProtocolDidFinishLoading:self]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { [self.client URLProtocol:self didFailWithError:error]; }
以上操作就可以实现UIWebView的缓存,谢谢观看
相关文章推荐
- iOS平台利用 NSURLProtocol 实现网络数据缓存
- 使用NSURLProtocol实现UIWebView的离线缓存
- 56.使用NSURLProtocol实现UIWebView的离线缓存-转载
- 使用NSURLProtocol实现UIWebView的离线缓存
- 使用NSURLProtocol实现UIWebView的离线缓存
- 11、Spring技术栈-整合Redis,通过Redis的Master-Slave实现缓存数据读写分离
- Android通过请求网络数据实现ListView,ListView的优化、图片的缓存、子控件的点击事件。
- 使用NSURLProtocol实现UIWebView的离线缓存
- 使用NSURLProtocol实现UIWebView的离线缓存
- 使用NSURLProtocol实现UIWebView的离线缓存
- iOS开发通过NSURLProtocol实现UIWebView的离线缓存(离线加载),OC版和Swift3.0版
- 使用NSURLProtocol实现UIWebView的离线缓存
- 使用NSURLProtocol实现UIWebView的离线缓存
- 使用NSURLProtocol实现UIWebView的离线缓存的简单实现
- NSURLProtocol实现对WKWebView加载的网页的数据缓存
- Step1数据系统技术(3.使用浏览器Cache和http状态码304实现的客户端缓存)
- 通过oms实现Oracle的数据备份
- DataView数据视图实现数据过滤,排序(代码调试通过)
- 通过js实现2个select控件的交换数据
- asp.net 2.0 使用sqlserver2005 新的通知数据缓存实现