前言
iOS開發(fā)過程中扛伍,有些頁面是用H5進(jìn)行開發(fā)徐勃,原生使用WebView
打開H5頁面的鏈接,但是這種方式有一個(gè)很大的缺陷撮胧,就是打卡H5頁面會(huì)很慢;因?yàn)镠5頁面一般都會(huì)引入各種各樣的資源上荡,有js
趴樱、css
、圖片等等酪捡;這些資源在每一次打開H5頁面的時(shí)候,會(huì)逐步通過網(wǎng)絡(luò)請(qǐng)求下載到頁面上纳账,所以導(dǎo)致每一次打卡頁面都比較慢逛薇;
那有沒有一種辦法處理呢?
那就是把這些資源進(jìn)行緩存疏虫,只在第一次打開的時(shí)候永罚,進(jìn)行下載,并緩存到本地卧秘;后面再次打開的時(shí)候呢袱,就直接取緩存中的數(shù)據(jù);
一翅敌、WKURLSchemeHandler介紹
WKURLSchemeHandler
是iOS11后開放出來的API羞福,可通過WKURLSchemeHandler
檢測到WKWebView
中的網(wǎng)絡(luò)請(qǐng)求,通過原生進(jìn)行處理蚯涮;
二治专、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,不走系統(tǒng)斷言,走自己的handler處理
} else {
return [self bbhandlesURLScheme:urlScheme];
}
}
@end
2张峰、創(chuàng)建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設(shè)置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)