iOS WebView/WKWebView 請求 資源 攔截 緩存 優化嘗試

UIWebView 使用URLProtocol解決

UIWebView的請求可以通過NSURLPtotol攔截,既可以攔截,也可以用本地的資源直接返回,可以實現資源本地化等各種需求,網上好多這種文章,所以此次不過多提及,主要針對WKWebView(僅考慮iOS11及以上,iOS11以下的網上也有,也是注冊私有方法)

WKWebView實現類似URLProtocol方法

通過繼承WKURLSchemeHandler的對象實現攔截

WKWebViewConfiguration類有如下方法:


image.png

可以讓我們通過自定義的協議去實現攔截,但是默認是不允許設置Http及Https以及FTP等請求的,所以需要我們自己修改一下(系統是否支持,需要我們自己
調用+[WKWebView handlesURLScheme:]來測試一下),
步驟如下:

1. WKWebViewConfiguration設置自定義WKURLSchemeHandler (有2種設置方式)
    WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
    CustomURLSchemeHandler *handler = [CustomURLSchemeHandler new];
    
    //支持https和http的方法1  這個需要去hook +[WKwebview handlesURLScheme]的方法,可以去看WKWebView+Custome類的實現
    [configuration setURLSchemeHandler:handler forURLScheme:@"https"];
    [configuration setURLSchemeHandler:handler forURLScheme:@"http"];
    
    //hook系統的方法2   xcode11可能會運行直接崩潰,因為用到了私有變量,xcode會檢測,但是xcode10沒問題,應該是xcode做了攔截,不影響使用
//    NSMutableDictionary *handlers = [configuration valueForKey:@"_urlSchemeHandlers"];
//    handlers[@"https"] = handler;//修改handler,將HTTP和HTTPS也一起攔截
//    handlers[@"http"] = handler;
    WKWebView *wk = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height-200) configuration:configuration];
    [self.view addSubview:wk];
    [wk loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];

自己寫一個繼承WKURLSchemeHandler協議的對象

#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN

@interface CustomURLSchemeHandler : NSObject <WKURLSchemeHandler>

@end

NS_ASSUME_NONNULL_END
//這里攔截到URLScheme為customScheme的請求后,根據自己的需求,返回結果,并返回給WKWebView顯示
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask{
    NSURLRequest *request = urlSchemeTask.request;
    NSLog(@"request = %@",request);
    
    //如果是我們替對方去處理請求的時候
    if (!manager) {
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:config];
        //這個acceptableContentTypes類型自己補充,demo不寫太多
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects: @"text/html", nil];
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    }
    NSURLSessionDataTask *task = [manager  dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        [urlSchemeTask didReceiveResponse:response];
        [urlSchemeTask didReceiveData:responseObject];
        [urlSchemeTask didFinish];
    }];
    [task resume];

    //如果是返回本地資源的話
//    UIImage *image = [UIImage imageNamed:@"yang.jpg"];
//    NSData *data = UIImageJPEGRepresentation(image, 1.0);
//    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:urlSchemeTask.request.URL MIMEType:@"image/jpeg" expectedContentLength:data.length textEncodingName:nil];
//    [urlSchemeTask didReceiveResponse:response];
//    [urlSchemeTask didReceiveData:data];
//    [urlSchemeTask didFinish];
}

- (void)webView:(WKWebView *)webVie stopURLSchemeTask:(id)urlSchemeTask {
    NSLog(@"stop = %@",urlSchemeTask);
}
@end

然后就可以實現攔截,以訪問的百度網頁為例,打印如下:


image.png

即可攔截或者替換本地資源

demo地址:https://github.com/yangfangkuo/WKWebViewHandleDemo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容