2017-04-23 63 views
1

我已經搜索了整個互聯網,找不到解決方案,因此決定向專家諮詢,這甚至有可能。是否有可能在webview上顯示之前預加載html

我有一個博客,我正在開發iOS應用程序,但它需要太多時間加載內容。

因此,有可能在用戶打開文章之前預載所有文章的html(而不是圖像),就像FB即時文章一樣。 FB即時文章被預先加載和緩存,當用戶打開它時,它會在閃存中打開,除非用戶打開它時下載的圖像。

目前我正在使用uiwebview,我正在用wkwebview替換它。

感謝您的幫助。

調用緩存

CachedArticles.shared.cacheArticles(self.articles) { success 
    print("cache creation finished, success: \(success)") 
} 

調用的WebView

tableView.deselectRow(at: indexPath, animated: true) 
let webVC = storyboard!.instantiateViewController(withIdentifier:"NewsReaderViewController") as! NewsReaderViewController 
webVC.article = self.articles?[indexPath.row] 
navigationController?.pushViewController(webVC, animated: true) 

緩存類

import UIKit 

class CachedArticles: NSObject { 

static let shared: CachedArticles = CachedArticles() 

let cachePath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first! 

func cacheArticles(_ articles: [ArticalClass]?, completion: @escaping (Bool)->()) { 

    guard let articles = articles else { return } 

    DispatchQueue.global().async { 
     DispatchQueue.main.async { 
      UIApplication.shared.isNetworkActivityIndicatorVisible = true 
     } 

     var success = true 

     for article in articles { 
      guard let path = article.url, let url = URL(string: path), self.webArchive(forHeadline: article.headline!.replacingOccurrences(of: " ", with: "")) == nil else { continue } 

      print("caching article: \(article)") 
      do { 
       let data = try Data(contentsOf: url) 
       let url = self.cacheFileURL(forHeadline: article.headline!) 
       STWebArchiver().archiveHTMLData(data, textEncoding: "UTF-8", baseURL: url, completionBlock: { data in 
        (data! as NSData).write(toFile: url.path, atomically: true) 
       }) 
      } catch let error { 
       success = false 
       print("Error: \(error)") 
      } 
     } 

     DispatchQueue.main.async { 
      UIApplication.shared.isNetworkActivityIndicatorVisible = false 
      completion(success) 
     } 
    } 
} 

func webArchive(forHeadline: String?) -> URL? { 
    let url = cacheFileURL(forHeadline: forHeadline!) 
    return FileManager.default.fileExists(atPath: url.path) ? url : nil 
} 

private func cacheFileURL(forHeadline: String) -> URL { 
    let url = URL(fileURLWithPath: self.cachePath).appendingPathComponent(forHeadline.replacingOccurrences(of: " ", with: "")+".webarchive") 
    return url 
} 

} 

回答

2

您可以通過預覽中的HTTP請求獲取html文件並將其保存到緩存中,並在您真正輸入時檢查它是否在緩存中。

============================================== ===

4.24更新 有兩個因素

首先,我不知道如何產生的「文章」數組,如果它包含src網址。

其次,我已審閱STWebArchiver代碼,我發現它:

- (void)archiveHTMLData:(NSData *)aData 
     textEncoding:(NSString *)anEncoding 
      baseURL:(NSURL *)anURL 
    completionBlock:(void (^)(NSData *))completion { 
htmlDocPtr doc = htmlParseDoc((xmlChar *)[aData bytes], [anEncoding UTF8String]); 
NSArray *pathsForImagesAndScripts = [self valueForAttributeName:@"src" withEvaluatingXPath:@"//script[@src]|//img[@src]" inDocument:doc]; 
NSArray *pathsForStylesheets = [self valueForAttributeName:@"href" withEvaluatingXPath:@"//link[@rel='stylesheet'][@href]" inDocument:doc]; 
NSArray *resourcesPaths = [pathsForImagesAndScripts arrayByAddingObjectsFromArray:pathsForStylesheets]; 
NSArray *resourceUrls = [self absoluteURLsForPaths:resourcesPaths baseURL:anURL]; 
dispatch_async(dispatch_queue_create("Downloads", 0), ^{ 
    NSMutableDictionary *resources = [NSMutableDictionary dictionary]; 
    dispatch_apply([resourceUrls count], dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^(size_t i) { 
     NSURL *url = [resourceUrls objectAtIndex:i]; 
     NSString *urlString = [url absoluteString]; 
     BOOL unfetched = NO; 
     @synchronized (resources) { 
      unfetched = ![resources objectForKey:urlString]; 
      if (unfetched) { 
       [resources setObject:[NSNull null] forKey:urlString]; 
      } 
     } 
     if (unfetched) { 
      NSURLResponse *response; 
      NSError *error; 
      NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
      NSData *data = [NSURLConnection sendSynchronousRequest:request 
               returningResponse:&response 
                  error:&error]; 
      NSMutableDictionary *resourceArchive = [NSMutableDictionary dictionaryWithObjectsAndKeys: 
                urlString, @"WebResourceURL", 
                [response MIMEType], @"WebResourceMIMEType", 
                data, @"WebResourceData", nil]; 
      if ([response textEncodingName]) { 
       [resourceArchive setObject:[response textEncodingName] forKey:@"WebResourceTextEncodingName"]; 
      } 
      @synchronized (resources) { 
       [resources setObject:resourceArchive forKey:urlString]; 
      } 
     } 
    }); 
    NSMutableDictionary *archiveSource = [NSMutableDictionary dictionaryWithObject:[resources allValues] forKey:@"WebSubresources"]; 
    NSMutableDictionary *mainResource = [NSMutableDictionary dictionary]; 
    [mainResource setObject:aData forKey:@"WebResourceData"]; 
    [mainResource setObject:@"" forKey:@"WebResourceFrameName"]; 
    [mainResource setObject:@"text/html" forKey:@"WebResourceMIMEType"]; 
    [mainResource setObject:anEncoding forKey:@"WebResourceTextEncodingName"]; 
    [mainResource setObject:[anURL absoluteString] forKey:@"WebResourceURL"]; 
    [archiveSource setObject:mainResource forKey:@"WebMainResource"]; 
    NSData *webArchive = [NSPropertyListSerialization dataFromPropertyList:archiveSource 
                    format:NSPropertyListBinaryFormat_v1_0 
                  errorDescription:NULL]; 
    completion(webArchive); 
}); 
xmlFreeDoc(doc); 
} 

這意味着STWebArchiver緩存不僅純HTML文件,但也請求的資源。

+0

我厭倦了,但它也提取/下載圖像以及非常耗費數據。 –

+0

你能顯示代碼嗎? –

+0

感謝您的回覆。更新了代碼。 –

0

您可以通過創建他們事先做了 「貪婪」 的WebView的做法,他們是前甚至添加到查看層次結構並開始他們的請求。這假定每個webview實例都會顯示一個不導航到其他html頁面的頁面。 appDidFinishLaunching將是一個設置的地方。

+0

不幸的是,它可能導航到其他html頁面。 –

相關問題