RNCachingURLProtocol
参考文章:Drop-in Offline Caching for UIWebView (and NSURLProtocol)
能干什么事
- 缓存网页里的图片
- 连线的时候,缓存请求
- 离线的时候,显示最近一次的内容
怎么用
RNCachingURLProtocol 继承于 NSURLProtocol。每次下载 URL 后,都会 cache 到硬盘。cache 方式是 archive 内容到 Library/Caches 目录下。当我们想用的时候,就从这个目录下读取内容。
RNCachingURLProtocol cache 了所有的 HTTP/HTTPS traffic。这个库里只是对 http 进行了 cache,我们想要对 https cache的话,需要在 RNCachingURLProtocol - initialize 里修改支持的 scheme。
使用方法很简单:
- 导入 RNCachingURLProtocol 到工程内。
- 在 AppDelegate 的 didFinishLaunchingWithOptions 里注册:
[NSURLProtocol registerClass:[RNCachingURLProtocol class]];
然后,你就可以愉快的体验离线缓存了。
提升首次进入网页时的加载速度
无论是冷启动还是热启动,我们都想要快的打开APP,将内容瞬间展示给用户。
而当首页是UIWebView的时候,这个效果就大打折扣了。尤其,当CSS、JS多切复杂的时候。
如果能在首次进入的时候,显示本地缓存的网页,而不是走网络交互,那么速度会有很大的提升。就是用这种办法来变相的提高首次进入时的加载速度的。
当然,还有其他的方法,比如合理优化网页结构、增加CDN提升网站访问速度啊什么的,但是对于我们来说这些都是不可控的,同时也非一时之功。
大体上是当启动App的时候,WebView 加载本地缓存的请求。然后进入网页后,之后所有的操作都是走的服务器的数据,而不再走本地缓存。
具体如下:
- 在 didFinishLaunchingWithOptions 进行判断
- 首次安装,WebView 从服务器加载 URL
- 非首次安装,WebView 从 Cache 加载 URL
- 在 WebView 加载成功代理 webViewDidFinishLoad 中
- 设定之后的请求不在走缓存
- 在 WebView 加载失败代理 didFailLoadWithError 中
- 设定之后的请求不在走缓存
- WebView 从新加载一次URL
AppDelegate.m 里
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self handleNewVersionWithBlock:^(BOOL newVersion) {
if (newVersion) {
[RNCachingCustomStatus shared].loadFromCache = NO;
} else {
[RNCachingCustomStatus shared].loadFromCache = YES;
}
}];
[NSURLProtocol registerClass:[RNCachingURLProtocol class]];
return YES;
}
ViewController.m 里
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CFAbsoluteTime endTime = (CFAbsoluteTimeGetCurrent() - self.startTime);
NSLog(@"endTime in %f ms", endTime *1000.0);
[RNCachingCustomStatus shared].loadFromCache = NO;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
// 当 cache 被清除后,通过 RNCachingURLProtocol 加载URL会失败,需要在这里进行处理
[RNCachingCustomStatus shared].loadFromCache = NO;
NSString *url = @"https://0.u.7518.cn/";
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
}
这样做的结果:
- 处理之前平均进入一次首页要2.4秒左右
- 处理之后平均进入一次首页只需要1.5秒左右
效果提升的还是很大的。