详解iOS webview加载时序和缓存问题总结
iOS webView的加载时序
UIWebView加载顺序:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSLog(@"开始请求webview:%@",request.URL.relativeString); return YES; } - (void)webViewDidStartLoad:(UIWebView *)webView { NSLog(@"开始加载webview"); } - (void)webViewDidFinishLoad:(UIWebView *)webView { NSLog(@"结束加载webview"); } - (void)webView:(UIWebView *)webView didFailLoadWithError:(nonnull NSError *)error { NSLog(@"webView加载失败"); }
加载的结果:
2017-04-27 08:53:00.535 H5页面调试[1273:150877] 开始请求webview:http://xxxx/index1.html
2017-04-27 08:53:00.537 H5页面调试[1273:150877] 开始加载webview
-----------------显示开始加载html CSS js 和图片资源等(JS引擎单线程顺序执行)---------------
2017-04-27 08:53:01.069 H5页面调试[1273:150877] 结束加载webview
WKWebView加载时序:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSLog(@"webview开始请求"); decisionHandler(WKNavigationActionPolicyAllow); } - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { NSLog(@"webView开始加载"); } - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { NSLog(@"webview开始收到响应"); decisionHandler(WKNavigationResponsePolicyAllow); } -----------------显示开始加载html CSS js 和图片资源等(JS引擎单线程顺序执行)--------------- - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation { NSLog(@"1"); } - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { NSLog(@"webview结束加载内容"); } - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{ NSLog(@"webview加载失败"); } - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{ NSLog(@"开始重定向的函数"); } - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler { NSLog(@"2"); completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); }
iOS webView加载html5缓存
1.加载html5的过程
每次加载一个HTML5页面,都会有较多的请求。除了HTML主URL自身的请求外,HTML外部引用的JS、CSS、字体文件、图片都是一个独立的HTTP请求,每一个请求都串行的(可能有连接复用)。
2.设置清除html5页面缓存
html5端设置meta标签:
<meta http-equiv="Pragma" content="no-cache" /><meta http-equiv="Cache-Control" content="no-cache" /><meta http-equiv="Expires" content="0" />
ios:设置加载的网络请求不采用本地缓存和远程缓存
PS:设置上面的只是紧紧可以保证html文件每次从服务器中获取,不从缓存文件中拿,而对于外联CSS JS图片等文件仍旧是从缓存中获取的;
3.设置css JS文件不从缓存中读取
通过添加版本号的和随机数的方法,保证每次加载JS CSS连接都是最新的,通常的做法是添加一个版本号,在每次更新了JS CSS时给版本号+1;保证没有更新时采用缓存文件
有更新可以从服务中获取;
解决方法
1、随机数法
方法一:
document.write( " <script src='test.js?rnd= " + Math.random() + " '></s " + " cript> " )
方法二:
var js = document.createElement( " script " ) js.src = " test.js " + Math.random() document.body.appendChild(js)
这样采用随机数的话, js文件将永远得不到缓存,每次都必须重新从服务器加载,即使没有任何更改。
大家如果经常上国外网站的话,可以看到他们通常采用这样的方式来解决:
<script src="test.js?ver=113"></script>
其中 ver=113 的 113就是版本号
这样真正做到了应该缓存的时候缓存静态文件,当版本有更新的时候从获取最新的版本,并更新缓存。
对于图像 <img src="test.jps?ver=版本号"> 来有效利用和更新缓存.
4.iOS清除缓存文件
- (void)removeWebCache{ if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) { NSSet *websiteDataTypes= [NSSet setWithArray:@[ WKWebsiteDataTypeDiskCache, //WKWebsiteDataTypeOfflineWebApplication WKWebsiteDataTypeMemoryCache, //WKWebsiteDataTypeLocal WKWebsiteDataTypeCookies, //WKWebsiteDataTypeSessionStorage, //WKWebsiteDataTypeIndexedDBDatabases, //WKWebsiteDataTypeWebSQLDatabases ]]; // All kinds of data //NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes]; NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0]; [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{ }]; [[NSURLCache sharedURLCache] removeAllCachedResponses]; } else { //先删除cookie NSHTTPCookie *cookie; NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (cookie in [storage cookies]) { [storage deleteCookie:cookie]; } NSString *libraryDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; NSString *webkitFolderInLib = [NSString stringWithFormat:@"%@/WebKit",libraryDir]; NSString *webKitFolderInCaches = [NSString stringWithFormat:@"%@/Caches/%@/WebKit",libraryDir,bundleId]; NSString *webKitFolderInCachesfs = [NSString stringWithFormat:@"%@/Caches/%@/fsCachedData",libraryDir,bundleId]; NSError *error; /* iOS8.0 WebView Cache的存放路径 */ [[NSFileManager defaultManager] removeItemAtPath:webKitFolderInCaches error:&error]; [[NSFileManager defaultManager] removeItemAtPath:webkitFolderInLib error:nil]; /* iOS7.0 WebView Cache的存放路径 */ [[NSFileManager defaultManager] removeItemAtPath:webKitFolderInCachesfs error:&error]; NSString *cookiesFolderPath = [libraryDir stringByAppendingString:@"/Cookies"]; [[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&error]; [[NSURLCache sharedURLCache] removeAllCachedResponses]; } }
关于保存在沙盒中的缓存文件如下图:
5.针对UIWebView出现的内存泄漏方法(网上)
- (void)webViewDidFinishLoad:(UIWebView *)webView { //防止内存泄漏 [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"]; //本地webkit硬盘图片的缓存; [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];//自己添加的,原文没有提到。 //静止webkit离线缓存 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitOfflineWebApplicationCacheEnabled"];//自己添加的,,原文没有提到。 [[NSUserDefaults standardUserDefaults] synchronize]; } - (void)dealloc { [webView loadHTMLString:@"" baseURL:nil]; [webView stopLoading]; [webView removeFromSuperview]; webView = nil; [[NSURLCache sharedURLCache] removeAllCachedResponses]; [[NSURLCache sharedURLCache] setDiskCapacity:0]; [[NSURLCache sharedURLCache] setMemoryCapacity:0]; NSLog(@"释放了webview"); } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ int cacheSizeMemory = 4*1024*1024; // 4MB int cacheSizeDisk = 32*1024*1024; // 32MB NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"]; [NSURLCache setSharedURLCache:sharedCache]; } - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { [[NSURLCache sharedURLCache] removeAllCachedResponses]; }
PS:经测试好像没什么卵用,先放在这里反正写了也没什么坏处
确定
1.如果没有CDN缓存影响;每次杀死APP后重新进入,第一次加载webview,都会加载全部的数据资源(外联js,外联css,图片等)退出去后,如果在没有更新js,css内容时,默认只会加载html内容,PS:html中的内容 在每次加载webView中都会从服务器中更新一下;
2.如果js css后面都添加了版本号,那么在每次更新版本号时,或者说资源链接变化时,webView一定会重新加载新的内容;如下图
<script type="text/javascript" src="index1.js?v=1.0.0"></script>
疑问?
1.经测试发现,JS CSS没有加版本号,更新JS CSS的内容有时候也会及时从服务器中更新获取,大多数时候又不会更新;不知道是不是跟web服务器的缓存策略有关,还是文件超期了?还是CDN缓存有关?
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
- shell基础学习总结(二) (r3笔记第72天)
- 对IMP-00013问题的思考(r3笔记第71天)
- 搭建LSTM(深度学习模型)做文本情感分类的代码
- 【大牛经验】高吞吐低延迟Java应用的垃圾回收优化
- shell的图形化实现简单示例(r3笔记第70天)
- 关于查询转换的一些简单分析(三) (r3笔记第69天)
- 【大牛经验】Web服务器的工作原理
- 使用shell定制addm脚本(r3笔记第88天)
- 【专业技术第十三讲】指针和内存泄露
- 【Java案例】余弦函数
- MySQL数据类型(r3笔记第87天)
- NLP真实项目:利用这个模型能够通过商品评论去预测一个商品的销量
- python + selenium + PhantomJS 获取腾讯应用宝APP评论
- 简单实用的sql小技巧(第二篇)(r3笔记第86天)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- flink源码分析之TaskManager启动篇
- 【面试说】一年半前端 Bigo 一二三 面
- 【前端进阶】深入浅出浏览器事件循环【内附练习题】
- 【面试说】一年半前端 Shopee 面经
- 【前端进阶】深入浅出 JavaScript 中的 this
- 手把手带你玩转 AWS Lambda
- Guava 中的 Stopwatch 是个什么鬼?
- Mybatis接口Mapper内的方法为啥不能重载?
- 基于K-Means聚类算法的主颜色提取
- 扩展之Tensorflow2.0 | 21 Keras的API详解(下)池化、Normalization层
- 一个真实问题,搞定三个冷门pandas函数
- conda管理C源代码程序的时候总是出现库文件冲突或者缺失
- 如何获取非模式生物KEGG PATHWAY的基因集并用clusterProfile做GSEA?
- 通过视频着色进行自监督跟踪
- Python爬虫:一些常用的爬虫技巧总结