1. 程式人生 > >iOS WebView載入url快取問題

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=113113就是版本號 這樣真正做到了應該快取的時候快取靜態檔案,當版本有更新的時候從獲取最新的版本,並更新快取。 對於影象 <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 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一定會重新載入新的內容;如下:





<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>