級別:★☆☆☆☆
標籤:「iOS WKWebView」「自定義WKWebView顯示內容」
做者: WYW
審校: QiShare團隊php
筆者最近了解了部分關於自定義WKWebView的內容,在本文中將主要說明WKWebView的內容過濾規則(WKContentRuleList)及WKWebView加載相冊中圖片顯示到WKWebView中的方式(WKURLSchemeHandler)。html
WKContentRuleList是應用於Web內容的編譯規則列表,適用於 iOS11.0+ 的設備。咱們能夠經過給webView.configuration.userContentController添加WKContentRuleList,使WebView的加載遵照相關規則。git
舉個例子好比咱們想要訪問 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·H 和 dac_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"]]];
複製代碼
使用 block 能夠阻塞部分 URL 不能正常顯示。下文中筆者阻塞加載特定的圖片 URL 的效果以下:sass
關鍵代碼以下:
- (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 結合 if-domain(控制若是是某個域名下),resource-type(把image類型放到數組中)阻塞了簡書的圖片資源的訪問,效果以下:
相關代碼以下:
//! 配置阻塞某些資源的加載
- (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 是用於加載自定義的 URL Schemes(非WKWebView自身原本就能處理的https等URL Scheme)資源的時候的協議。筆者作了一個經過自定義協議,加載相冊中圖片回顯到WebView的Demo。
下圖展現使用WKURLSchemeHandler,控制從相冊中獲取圖片回顯到WebView的img。整個過程當中,咱們須要設置給WKWebViewConfiguration 設置 URLSchemeHandler 處理對象及要處理的 URLScheme。這樣當加載到咱們要處理的 URLScheme 的時候,就會調用 WKURLSchemeHandler 的 startURLSchemeTask、stopURLSchemeTask 的代理方法。咱們就能夠在相應代理方法中準備、並提供相應數據內容給WebView任務,進行相應數據顯示。
筆者用到的相關代碼以下:
- (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: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) - 集合類型
奇舞週刊