自定義WKWebView顯示內容(一)

級別:★☆☆☆☆
標籤:「iOS WKWebView」「自定義WKWebView顯示內容」
做者: WYW
審校: QiShare團隊php


筆者最近了解了部分關於自定義WKWebView的內容,在本文中將主要說明WKWebView的內容過濾規則(WKContentRuleList)及WKWebView加載相冊中圖片顯示到WKWebView中的方式(WKURLSchemeHandler)。html

WKContentRuleList make-https

WKContentRuleList是應用於Web內容的編譯規則列表,適用於 iOS11.0+ 的設備。咱們能夠經過給webView.configuration.userContentController添加WKContentRuleList,使WebView的加載遵照相關規則。git

  • WKContentRuleList的make-https能夠更改http的URL爲https,具備指定(非默認)端口的URL和使用其餘協議的連接不受影響。

舉個例子好比咱們想要訪問 www.so.com,可是寫 URL 的時候寫成了 www.so.com ,而 www.so.com 也能夠正常訪問,此時若是沒有配置ATS的狀況,若是配置了 make-https 那麼應用中的WebView也能正常加載。github

注意:若是咱們要訪問的另外一個網址 www.xxx.com ,寫URL的時候寫成了http://www.xxx.com,此時若是 xxx.com 不支持 https,那麼WebView就沒法正常加載。這部份內容以前筆者還理解錯了,後來感謝 Xs·Hdac_1033 的指正,並提供了一個驗證當前訪問的url 是否支持https的命令,下邊的這個命令的輸出結果也能夠用於配置 Info.plist 文件中針對某些 URL 的 ATS 配置規則。web

nscurl --ats-diagnostics URL
複製代碼

如:測試http://www.so.com正則表達式

nscurl --ats-diagnostics http://so.com
Starting ATS Diagnostics

Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://so.com.
A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error.
Use '--verbose' to view the ATS dictionaries used and to display the error received in URLSession:task:didCompleteWithError:.
================================================================================

Default ATS Secure Connection
---
ATS Default Connection
Result : PASS
---

複製代碼

像上邊示例中只有 Result 有 Pass 的狀況,使用 make-https 對 http 的 URL 配置纔有用。json

相關代碼(編譯添加RuleList相關代碼在iOS 11.0+才支持):數組

- (void)configMakeHttps {

    // 提供ContentRule規則
     NSArray *jsonArr =
      @[@{
            @"trigger": @{
                // 匹配全部的 URL,值爲正則表達式
                    @"url-filter": @".*"
            },
            @"action": @{
                // 設置類型爲對 URL 作 make-https 處理
                    @"type": @"make-https"
            }
      },
      ];
   
    [self compileContentRuleWithJsonArray:jsonArr];
}
複製代碼
- (void)compileContentRuleWithJsonArray:(NSArray *)jsonArr {
    
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonArr options:NSJSONWritingPrettyPrinted error:nil];
    NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    
    // 編譯ContentRule規則
    [[WKContentRuleListStore defaultStore] compileContentRuleListForIdentifier:@"ContentBlockingRules"
                                                        encodedContentRuleList:jsonStr
                                                             completionHandler:^(WKContentRuleList *ruleList, NSError *err) {
        if (ruleList) {
            // 在 WebView 的配置中添加 RuleList
            [self.webView.configuration.userContentController addContentRuleList:ruleList];
            NSLog(@"編譯的ruleList:%@", ruleList);
        } else {
            NSLog(@"編譯的ruleList爲空,錯誤信息:%@", err);
        }
    }];
}
複製代碼

下邊的請求就會被轉換爲請求 www.so.com緩存

[_webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.so.com"]]];
複製代碼

WKContentRuleList block

  • block的做用:中止加載資源。 若是已緩存資源,則忽略緩存。

block阻塞加載特定URL

使用 block 能夠阻塞部分 URL 不能正常顯示。下文中筆者阻塞加載特定的圖片 URL 的效果以下:sass

contentRuleList1.png

關鍵代碼以下:

- (void)configBlockURL {
    
    NSArray *jsonArr =
        @[
            @{
                @"trigger": @{
                        // 配置特定的URL 也能夠經過正則匹配符合其餘條件的URL
                        @"url-filter": @"(https://upload.jianshu.io/users/upload_avatars/2628633/c6a17aeb-04be-4862-9b2d-01db2a3dd16c.png)",
    
                },
                 @"action": @{
                         @"type": @"block"
                 }
             },
            // 下邊字典 筆者又測試了一次make-https 把http 轉爲https
            @{
                  @"trigger": @{
                          @"url-filter": @".*"
                  },
                  @"action": @{
                          @"type": @"make-https"
                  }
            },
        ];
    [self compileContentRuleWithJsonArray:jsonArr];
}
複製代碼
[_webView loadFileURL:[[NSBundle mainBundle] URLForResource:@"QiContentRule" withExtension:@"html"] allowingReadAccessToURL:[[NSBundle mainBundle] bundleURL]];
複製代碼

筆者用到的QiContentRule.html內容以下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
            <title>QiWKWebView</title>
    </head>
    <body>
        測試加載支持https的http連接的圖片http://upload.jianshu.io/collections/images/1673367/8.png
        <br>
        <img src="http://upload.jianshu.io/collections/images/1673367/8.png?imageMogr2/auto-orient/strip" width="300">
            <br>
            測試block圖片加載https://upload.jianshu.io/users/upload_avatars/2628633/c6a17aeb-04be-4862-9b2d-01db2a3dd16c.png
            <br>
<!-- <img src="http://p0.qhimg.com/d/QiShare/QiShare.png" width="300" height="300">-->
            <br>
            <img src="https://upload.jianshu.io/users/upload_avatars/2628633/c6a17aeb-04be-4862-9b2d-01db2a3dd16c.png" alt="測試block圖片 圖片加載失敗" width="300" height= "300">
            <br>
    </body>
</html>
複製代碼

block阻塞加載某些資源

筆者使用 block 結合 if-domain(控制若是是某個域名下),resource-type(把image類型放到數組中)阻塞了簡書的圖片資源的訪問,效果以下:

QiContentRuleList3.gif

相關代碼以下:

//! 配置阻塞某些資源的加載
- (void)configBlockLoadSomeResource {
    
        NSArray *jsonArr =
      @[
    // block資源
      @{
          @"trigger": @{
                  @"url-filter": @".*",
                  // @"resource-type": @[@"image", @"style-sheet", @"font", @"script", @"document", @"media", @"popup"],
                  @"resource-type": @[@"image"],
                  // @"unless-domain": @[@"www.jianshu.com"],
                  @"if-domain": @[@"www.jianshu.com"],
          },
          @"action": @{
                  //block:Stops loading of the resource. If the resource was cached, the cache is ignored.
                  // 中止加載資源。 若是已緩存資源,則忽略緩存。
                   @"type": @"block"
          }
      }
      ];
    [self compileContentRuleWithJsonArray:jsonArr];
}
複製代碼
[_webView loadRequest: [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://www.jianshu.com/u/3db23baa08c7"]]];
複製代碼

更多ContentRule的規則見 Creating a Content Blocker

WKURLSchemeHandler

WKURLSchemeHandler 是用於加載自定義的 URL Schemes(非WKWebView自身原本就能處理的https等URL Scheme)資源的時候的協議。筆者作了一個經過自定義協議,加載相冊中圖片回顯到WebView的Demo。

WKURLSchemeHandler加載相冊圖片回顯到WKWebView

下圖展現使用WKURLSchemeHandler,控制從相冊中獲取圖片回顯到WebView的img。整個過程當中,咱們須要設置給WKWebViewConfiguration 設置 URLSchemeHandler 處理對象及要處理的 URLScheme。這樣當加載到咱們要處理的 URLScheme 的時候,就會調用 WKURLSchemeHandler 的 startURLSchemeTask、stopURLSchemeTask 的代理方法。咱們就能夠在相應代理方法中準備、並提供相應數據內容給WebView任務,進行相應數據顯示。

QiCustomResource.gif

筆者用到的相關代碼以下:

- (void)loadView {

    WKWebViewConfiguration *webConfig = [WKWebViewConfiguration new];
    _schemeHandler = [QiCustomSchemeHandler new];
    [webConfig setURLSchemeHandler:_schemeHandler forURLScheme:@"qiLocal"];

    _webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webConfig];
    _webView.allowsBackForwardNavigationGestures = YES;
    _webView.backgroundColor = [UIColor whiteColor];
    self.view = _webView;
}
複製代碼
[_webView loadFileURL:[[NSBundle mainBundle] URLForResource:@"QiCustomResource" withExtension:@"html"] allowingReadAccessToURL:[[NSBundle mainBundle] bundleURL]];
複製代碼
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask {
    
    if ([urlSchemeTask.request.URL.absoluteString hasPrefix:@"qilocal://"]) { // qiLocal
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageDataBlock = ^(NSData * _Nonnull data, NSURLResponse * _Nonnull response) {
                [urlSchemeTask didReceiveResponse:response];
                [urlSchemeTask didReceiveData:data];
                [urlSchemeTask didFinish];
            };
            UIImagePickerController *imagePicker = [UIImagePickerController new];
            imagePicker.delegate = self.sourceViewController;
            imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            [self.sourceViewController showViewController:imagePicker sender:nil];
            self.imagePickerController = imagePicker;
        });
    }
}
複製代碼

筆者用到的 QiCustomResource.html 以下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
            <title>QiWKWebView</title>
    </head>
    <body>
        <a href="qiLocal://locaResource.com" rel="external nofollow" target="_top">QiLocalCustomResource</a>
        <br>
        <img src="qiLocal://locaResource.com" alt="從手機端獲取圖片" width="300">
    </body>
</html>

複製代碼

Demo

詳情見Demo:QiWKWebView

參考學習網址


小編微信:可加並拉入《QiShare技術交流羣》。

關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)

推薦文章:
Swift 5.1 (6) - 函數
Swift 5.1 (5) - 控制流
Xcode11 新建工程中的SceneDelegate
iOS App啓動優化(二)—— 使用「Time Profiler」工具監控App的啓動耗時
iOS App啓動優化(一)—— 瞭解App的啓動流程
iOS WKWebView的基本使用
Swift 5.1 (4) - 集合類型
奇舞週刊

相關文章
相關標籤/搜索