iOS WebView載入url快取問題
在做青海展廳專案時,將本應放在觸控式螢幕的h5放在iPad pro上,於是做了個APP,寫了個webView來load url request。但是由於在除錯階段,做h5的童鞋經常修改,然後釋出到伺服器上,我們發現,有時候修改,iPad會同步,有時候卻不會,尤其上他修改了載入vedio的部分,重啟APP也不好使。
然後我發現,
ios:設定載入的網路請求不採用本地快取和遠端快取
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:_urlString]];
[self.webView loadRequest:request];
PS:設定上面的只是僅僅可以保證html檔案每次從伺服器中獲取,不從快取檔案中拿,而對於外聯CSS JS圖片等檔案仍舊是從快取中獲取的;
h5設定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=版本號" > 來有效利用和更新快取.
```
iOS清除快取檔案
<div class="se-preview-section-delimiter"></div>
(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];
}
}
關於儲存在沙盒中的快取檔案如下圖:
![關於h5儲存在沙盒中的快取檔案如下圖](https://img-blog.csdn.net/20170901113543165?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWmhvbmdMdl9Ib25leU1vb24=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
另外,補充針對UIWebView出現的記憶體洩漏方法(網上)
<div class="se-preview-section-delimiter"></div>
(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 intcacheSizeDisk = 32*1024*1024; // 32MB
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@”nsurlcache”];
[NSURLCache setSharedURLCache:sharedCache];
}- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
總結:
> 1.如果沒有CDN快取影響;每次殺死APP後重新進入,第一次載入webview,都會載入全部的資料資源(外聯js,外聯css,圖片等)退出去後,如果在沒有更新js,css內容時,預設只會載入html內容,PS:html中的內容 在每次載入webView中都會從伺服器中更新一下;
> 2.如果js css後面都添加了版本號,那麼在每次更新版本號時,或者說資源連結變化時,webView一定會重新載入新的內容;如下:
<div class="se-preview-section-delimiter"></div>
“`
- (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];
}
總結:
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>