美文网首页
WKWebView(一)资源缓存

WKWebView(一)资源缓存

作者: fanren | 来源:发表于2024-04-16 19:44 被阅读0次

    前言

    iOS开发过程中,有些页面是用H5进行开发,原生使用WebView打开H5页面的链接,但是这种方式有一个很大的缺陷,就是打卡H5页面会很慢;因为H5页面一般都会引入各种各样的资源,有jscss、图片等等;这些资源在每一次打开H5页面的时候,会逐步通过网络请求下载到页面上,所以导致每一次打卡页面都比较慢;
    那有没有一种办法处理呢?
    那就是把这些资源进行缓存,只在第一次打开的时候,进行下载,并缓存到本地;后面再次打开的时候,就直接取缓存中的数据;

    一、WKURLSchemeHandler介绍

    WKURLSchemeHandler是iOS11后开放出来的API,可通过WKURLSchemeHandler检测到WKWebView中的网络请求,通过原生进行处理;

    二、WKURLSchemeHandler使用

    1、WKWebview添加Catetory

    #import <objc/runtime.h>
    
    @implementation WKWebView(WIICustomer)
    
    
    + (void)load 
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Method originalMethod1 = class_getClassMethod(self, @selector(handlesURLScheme:));
            Method swizzledMethod1 = class_getClassMethod(self, @selector(bbhandlesURLScheme:));
            method_exchangeImplementations(originalMethod1, swizzledMethod1);
        });
    }
     
    + (BOOL)bbhandlesURLScheme:(NSString *)urlScheme {
        if ([urlScheme isEqualToString:@"http"] ||
            [urlScheme isEqualToString:@"https"]) {
            return NO;  //这里让返回NO,不走系统断言,走自己的handler处理
        } else {
            return [self bbhandlesURLScheme:urlScheme];
        }
    }
    
    @end
    

    2、创建WKURLSchemeHandler类

    class WIIWebViewSchemeHandler: NSObject & WKURLSchemeHandler {
        
        public var module = "Test"
    
        func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
            guard let url = urlSchemeTask.request.url else {
                urlSchemeTask.didFinish()
                return
            }
            let urlPath = url.absoluteString
            let key = urlPath.md5()
            guard let localFilePath = self.getLocalFilePath(key: key) else {
                urlSchemeTask.didFinish()
                return
            }
            if FileManager.default.fileExists(atPath: localFilePath) {
                let fileHandle = FileHandle(forReadingAtPath: localFilePath)
                if let data = fileHandle?.readDataToEndOfFile() {
                    let mimeType = self.getMimeType(key: key)
                    let response = self.createURLResponse(url: url, data: data, mimeType: mimeType)
                    urlSchemeTask.didReceive(response)
                    urlSchemeTask.didReceive(data)
                    urlSchemeTask.didFinish()
                    try? fileHandle?.close()
                    return
                }
                try? fileHandle?.close()
            }
            let session = URLSession.shared
            let task = session.dataTask(with: url) { data, response, err in
                if let data = data, let response = response {
                    let mimeType = response.mimeType ?? "text/plain"
                    self.saveMimeType(mimeType, key: key)
                    
                    let urlResponse = self.createURLResponse(url: url, data: data, mimeType: mimeType)
                    urlSchemeTask.didReceive(urlResponse)
                    urlSchemeTask.didReceive(data)
                    urlSchemeTask.didFinish()
                    
                    try? data.write(to: URL(fileURLWithPath: localFilePath), options: Data.WritingOptions.atomic)
                } else {
                    urlSchemeTask.didFailWithError(err ?? NSError())
                }
            }
            task.resume()
        }
        
        func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
            
        }
    }
    
    extension WIIWebViewSchemeHandler {
        func createURLResponse(url: URL, data: Data, mimeType: String) -> URLResponse {
            return URLResponse(url: url, mimeType: mimeType, expectedContentLength: data.count, textEncodingName: nil)
        }
    }
    extension WIIWebViewSchemeHandler {
        func getLocalFilePath(key: String) -> String? {
            guard let rootPath = self.urlCacheRootFilePath() else {
                return nil
            }
            return "\(rootPath)/\(key)"
        }
        
        func urlCacheRootFilePath() -> String? {
            guard let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else {
                return nil
            }
            let directoryPath = "\(path)/\(self.module)"
            if FileManager.default.fileExists(atPath: directoryPath) {
                return directoryPath
            }
            try? FileManager.default.createDirectory(atPath: directoryPath, withIntermediateDirectories: true)
            return directoryPath
        }
    }
    
    extension WIIWebViewSchemeHandler {
        func getMimeType(key: String) -> String {
            return UserDefaults.standard.string(forKey: key) ?? ""
        }
        
        func saveMimeType(_ type: String, key: String) {
            UserDefaults.standard.setValue(type, forKey: key)
        }
    }
    

    3、WKWebView设置URLScheme

    let config = WKWebViewConfiguration()
    let handler = WIIWebViewSchemeHandler()
    config.setURLSchemeHandler(handler, forURLScheme: "http")
    config.setURLSchemeHandler(handler, forURLScheme: "https")
    self.webview = WIIWebView(frame: self.view.bounds, configuration: config)
    

    相关文章

      网友评论

          本文标题:WKWebView(一)资源缓存

          本文链接:https://www.haomeiwen.com/subject/ewnjxjtx.html