7

I need to save the content loaded on the WKWebView for offline reading including images. Then the users can view the web page again even there is no network access.

Does WKWebView support caching it? How can I implement it?

The answer in "UIWebView webpage caching for offline viewing" is for UIWebview not for WKWebView, so they are different. And I also know we can enable app cache for WKWebViewCache but it will use private API which will be rejected.

lypw2009
  • 201
  • 3
  • 11
  • Assuming that the application has access to the internet, the UKWebView should request the domain and maintain it's state. Unless the `load()` function is triggered again. I don't think that what you are looking to do would be possible. Especially without using some sort of library that may or not be able to do it. Especially since from what I can see of the UKWebView docs doesn't suggest that you can save it (`takeSnapshot()` seems like the closest thing). This this the only thing on SO that I could find that was relevant: https://stackoverflow.com/q/30864893/6448167 – KSigWyatt May 14 '18 at 02:58
  • Is there any library can use for it? – lypw2009 May 14 '18 at 03:05
  • Try Mattress. Can't guarantee that it'll work anymore, but it's a place to start. https://github.com/buzzfeed/mattress – KSigWyatt May 14 '18 at 03:07
  • Mattress does not work with WKWebView. – lypw2009 May 14 '18 at 03:19
  • Please refer this link: https://stackoverflow.com/questions/29892898/enable-application-cache-in-wkwebview/44333359 – Khushbu May 14 '18 at 06:44
  • It used private API which is rejected by apple. – lypw2009 May 14 '18 at 07:18

2 Answers2

2
 //Two ways i know so far
//1st : after loading the page when user is online,get the html from WKWebView as follows :




webView.evaluateJavaScript("document.documentElement.outerHTML.toString()", 
                           completionHandler: { (html: Any?, error: Error?) in
    print(html)
})




//Second way is that inject script to get html from WKWebView as follows>

 let script = WKUserScript(source: javascriptString, injectionTime: injectionTime, forMainFrameOnly: true)
userContentController.addUserScript(script)
self.webView.configuration.userContentController.addScriptMessageHandler(self, name: "didGetHTML")
func userContentController(userContentController: WKUserContentController,
        didReceiveScriptMessage message: WKScriptMessage) { if message.name == "didGetHTML" {
            if let html = message.body as? String {
                print(html)
            }
        }
}
Vivek Kumar
  • 405
  • 5
  • 15
0
//To get image from html you need to implement like this 
import UIKit
import WebKit
import SwiftSoup
import AlamofireImage


class ViewController: UIViewController, WKNavigationDelegate {
    @IBOutlet weak var webView: WKWebView!
    @IBOutlet weak var imageView: UIImageView!

    let url = URL(string: "https://www.google.com")
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        webView.navigationDelegate = self

        let urlReq = URLRequest(url: url!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 1)
        webView!.load(urlReq)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        webView.evaluateJavaScript("document.documentElement.outerHTML.toString()",
                                   completionHandler: { (html: Any?, error: Error?) in
                                    do{
                                        let doc: Document = try SwiftSoup.parse(html as! String)
                                        let pngs: Elements = try doc.select("img[src$=.png]")
                                        let srcsStringArray: [String?] = pngs.array().map { try? $0.attr("src").description }
                                        for imgs in srcsStringArray {
                                            if let imgUrl = imgs {
                                                var finalUrl = URL(string: "")
                                                if imgUrl.contains("http") {
                                                    finalUrl = URL(string: String(format: imgUrl))
                                                } else {
                                                    finalUrl = URL(string: String(format: "%@%@", (self.url?.absoluteString)!, imgUrl))
                                                }
                                                self.imageView.af_setImage(withURL: finalUrl!)
                                                print(finalUrl) //debug URL
                                            }
                                        }
                                    } catch Exception.Error(let type, let message){
                                        print(type, message)
                                    } catch {
                                        print("error")
                                    }
        })
    }
}
Vivek Kumar
  • 405
  • 5
  • 15
  • 1
    How do you process the js and CSS files? There could be background image reference in the CSS file with relative path. – Rahatur Jan 16 '19 at 05:50