WKWebView 若是須要個性化配置,則應該使用如下方法進行初始化。javascript
- (instancetype)initWithFrame:(CGRect)frame
configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
複製代碼
示例代碼:css
WKWebViewConfiguration *conf = [WKWebViewConfiguration new];
WKWebView *wk = [[WKWebView alloc] initWithFrame:CGRectZero configuration:conf];
複製代碼
WKWebView 網頁的導航代理,能夠理解爲網頁的生命週期事件循環。html
WKWebView 網頁的UI交互代理,對於JS中的 UI 類型操做須要實現對應的方法,例如 window.alert
、window.confirm
等操做。前端
WKWebView 系統默認支持對網頁歷史記錄的管理,通過實際測試 302狀態碼的網頁請求不屬於歷史記錄,200狀態碼的網頁請求屬於正常的歷史記錄。java
支持僅對歷史記錄列表和數據的獲取jquery
WKBackForwardListItem 爲每一項歷史記錄的數據模型。ios
/*! @abstract The URL of the webpage represented by this item. */
@property (readonly, copy) NSURL *URL;
/*! @abstract The title of the webpage represented by this item. */
@property (nullable, readonly, copy) NSString *title;
/*! @abstract The URL of the initial request that created this item. */
@property (readonly, copy) NSURL *initialURL;
複製代碼
其中 initialURL 和 URL 的區別:web
initialURL
爲本次網頁加載的初始請求URL
爲本次網頁加載結束後的最終請求title
爲本次網頁加載結束時的 <title></title>
標籤正常狀況下,通常用 loadRequest 方法加載便可。ajax
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
複製代碼
loadData 和 loadHTML 也能加載網絡地址,原理都是經過先獲取 NSData 後,利用該方法加載,可是要注意獲取 NSData 的過程是同步,若是網絡請求較慢,會形成主線程阻塞。macos
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
// 直接加載H5數據
// [wk loadHTMLString:[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] baseURL:nil];
[wk loadData:data MIMEType:@"text/html" characterEncodingName:@"UTF-8" baseURL:nil];
複製代碼
loadHTMLString
和 loadData
中的參數說明:
baseURL
:會影響網頁加載過程當中css、js、圖片等資源文件的相對路徑,並不會影響絕對路徑。
MIMEType
:爲支持加載網頁的類型,有以下類型
文件拓展名 | MIMEType |
---|---|
png | image/png |
bmp/dib | image/bmp |
jpg/jpeg/jpg | image/ipeg |
gif | image/gif |
mp3 | audio/mpeg |
mp4/mpg4/m4v/mp4v | video/mp4 |
js | application/javascript |
application/pdf | |
text/txt | text/plain |
json | application/json |
xml | text/xml |
characterEncodingName
:當前返回信息的數據編碼格式:UTF-八、UTF-1六、UTF-3二、GBK、GB2312等,通常使用 UTF-8。
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL
allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macos(10.11), ios(9.0));
複製代碼
readAccessURL
參數不能爲空,不然會形成應用崩潰。readAccessURL
參數:容許訪問的資源路徑,若是是在 Bundle
中加載本地 HTML
,則須要設置該HTML
所在的Bundle
路徑,路徑設置好後,該目錄在WKWebView中被視爲沙盒目錄,HTML
就能夠訪問同級目錄下的資源文件。HTML主地址應爲:
YOUR_APP_PATH
/WKBundle.bundle/sandbox/index.html
readAccessURL應爲如下兩種:
YOUR_APP_PATH
/WKBundle.bundle/sandboxYOUR_APP_PATH
/WKBundle.bundle/readAccessURL
的參數爲當前HTML所在目錄容許訪問,該參數對Bundle目錄影響不大,對沙盒目錄影響較大。這個參數不能夠設置爲:YOUR_APP_PATH
/WKBundle.bundle/sandbox/js,不然會形成訪問出錯。
其他訪問本地HTML的方法
[wk loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:indexPath]]];
複製代碼
一樣,上文中的 loadData 和 loadHTML 也能夠訪問本地html,一樣也存在同步阻塞的問題。
Docuemnt
、Library
和 tmp
目錄
若是本地HTML放置在 Docuemnt ,Library 下的話, 則須要將目錄設置爲全部靜態資源的最外層。 例如目錄結構爲:
├─ html-demo
| ├─ common
| | ├─ index.css
| | └─ index.js
| ├─ pages
| | ├─ relative-common
| | | ├─ index.css
| | | └─ index.js
| | └─ index.html
複製代碼
若是將 html-demo 目錄放置在 Document、Library 目錄下
經過 [WKWebView loadFileURL:allowingReadAccessToURL:]
方法能夠訪問當前目錄下的相對資源,還須要設置指定訪問 allowingReadAccessToURL
下的資源,注意 allowingReadAccessToURL
須要設置 html
和 css
同時存在的最外層目錄,如上例中,咱們將 allowingReadAccessToURL
所需參數設置爲 html-demo
目錄的話,這樣既能訪問 common
目錄下的資源,也能訪問 relative-common
下的資源。
經過 [WKWebView loadRequest:]
方法訪問 index.html
的話,僅能訪問當前頁面所在目錄下的相對路徑資源,沒法訪問目錄外的資源,例如上例中,index.html
僅能訪問 relative-common
目錄下的資源,不能訪問 common
目錄下的資源。
經過 [WKWebView loadData:]
和 [WKWebView loadHTMLString:]
方法僅能加載當前HTML內容,沒法加載資源文件,這種加載模式下,因爲不須要訪問其餘路徑下的資源,屬於單頁渲染和加載,因此效率高。
若是將 html-demo 目錄放置在 tmp 目錄下
經過 [WKWebView loadRequest:]
方法訪問 index.html
的話,既能訪問 common
下的資源,也能訪問 relative-common
下的資源。
其他規則同上。
title
: 網頁的標題,通常爲 html
中的 <title></title>
中的內容URL
: 網頁的URL地址,爲最終加載的地址loading
: 網頁是否處於加載中,YES 加載中、 NO 加載完成estimatedProgress
: 網頁加載進度hasOnlySecureContent
: 網頁上的全部資源是否已經過https加載serverTrust
: 加載HTTPS請求服務端所信任的證書以上屬性均可以採用 KVO 觀察屬性變化:
// NSKeyValueObservingOptionNew 更改後的值
// NSKeyValueObservingOptionOld 更改前的值
// NSKeyValueObservingOptionInitial 觀察初始化的值(在註冊觀察服務時會調用一次觸發方法)
// NSKeyValueObservingOptionPrior 分別在值修改先後觸發方法(即一次修改有兩次觸發)
[wk addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionInitial context:NULL];
複製代碼
注意:添加觀察者模式後,必定要在合適的時機將觀察者模式移除,不然在 iOS10 如下的設備會形成崩潰,緣由是WKWebView 在釋放的時候,扔被強持有觀察者。
allowsBackForwardNavigationGestures
: 容許手勢交互進行頁面導航跳轉customUserAgent
: 自定義Web頁面的UserAgent,會覆蓋容器原有的 User-Agent
請求頭信息allowsLinkPreview
: 容許 3Dtouch 預覽頁面,壓力屏存在的狀況下webView 方法
canGoBack
: 是否能夠返回上一頁canGoForward
: 是否能夠前進一頁goBack
: 返回上一頁goForward
: 前進一頁eload
: 根據當前URL刷新頁面reloadFromOrigin
: 根據最初URL刷新頁面stopLoading
: 中止加載evaluateJavaScript
: 執行一段js代碼handlesURLScheme:(NSString *)urlScheme
: 攔截自定義請求協議,不容許攔截 http,https,ws,wsstakeSnapshotWithConfiguration
: 截圖配置 www.jianshu.com/p/67146af7e…,只能截取當前一屏畫面WKProcessPool
用於提供給 WKWebView
獲取Web內容的進程池,裏面包括 cookie
。當一個WebView 初始化,一個新的 Web 內容進程會從一個特殊的進程池中建立,或者一個已存在的進程會被使用。
WKProcessPool
自己沒有任何方法和屬性,經過實現單例進程池後,能夠達到 WKWebView
間共享 cookie
的能力,注意:若是在帳戶退出登陸後,單例進程須要釋放。
WKWebView 的偏好設置,支持如下設置:
minimumFontSize
: 最小字體設置,默認爲 0, H5
中 css
的 「font-size」
的值若是小於該值,則會使用該值做爲字體的最小尺寸。javaScriptEnabled
: 是否啓用 js
腳本,默認啓用,關閉則不會運算 js
腳本,加快渲染速度。javaScriptCanOpenWindowsAutomatically
: 使用容許使用 js
自動打開 Window
,默認不容許,js
在調用 window.open
方法的時候,必須將改值設置爲 YES
,才能從 WKUIDelegate
的代理方法中獲取到。WKUserScript *userScript = [[WKUserScript alloc] initWithSource:@"window.open('https://www.baidu.com')"
injectionTime:(WKUserScriptInjectionTimeAtDocumentStart)
forMainFrameOnly:YES];
複製代碼
屬性解釋:
injectionTime
: js
代碼的注入時機,支持 WKUserScriptInjectionTimeAtDocumentStart ,WKUserScriptInjectionTimeAtDocumentEND,分別表明頁面剛渲染前執行,和頁面渲染後執行。forMainFrameOnly
: 是否僅注入在主框架,仍是包括全部的 iframe
所有注入。使用 addUserScript
方法來添加 js
腳本。
若是注入時機爲在網頁渲染前,那麼網頁加載完畢後執行移除腳本操做,則腳本的運算結果並不會受影響,可是在網頁加載完畢前移除腳本的後,腳本將不會執行。
用於 Native 和 js 通訊,須要實現 WKScriptMessageHandler 協議。
WKUserContentController *userController = [[WKUserContentController alloc] init];
[userController addScriptMessageHandler:self name:@"JSBridge"];
[userController addScriptMessageHandler:self name:@"HWH5"];
conf.userContentController = userController;
複製代碼
JS代碼
window.webkit.messageHandlers.JSBridge.postMessage(...args)
window.webkit.messageHandlers.HWH5.postMessage(...args)
複製代碼
WKScriptMessageHandler
協議,並實現 didReceiveScriptMessage
方法接受消息,經過 message.name
區分不通的協議- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
NSLog(@"%@", message.name);
}
複製代碼
根據腳本消息通道名稱移除對應的腳本消息通道。能夠在任什麼時候機移除,移除後對應的js代碼也會移除。
developer.apple.com/documentati…
該配置須要結合內容過濾器編譯一塊兒使用,經過對 js 指定的規則編譯後獲得一個 WKContentRuleList
,而且經過 userController
添加進 WebView
中。
如下狀況中,WKWebView 在主動發送請求時不會攜帶 cookie 。
可使用 iOS11 的新API對 WKWebView 進行 cookie 的設置,利用如下代碼對 Cookie 進行持久化設置
NSHTTPCookie *cookie = ....;
[[WKWebsiteDataStore defaultDataStore].httpCookieStore setCookie:cookie ...];
複製代碼
示例代碼:
WKWebViewConfiguration *conf = [WKWebViewConfiguration new];
// 在初始化方法以前,設置 cookie
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithPropertie:...];
[[WKWebsiteDataStore defaultDataStore].httpCookieStore setCookie:cookie ...];
WKWebView *wk = [[WKWebView alloc] initWithFrame:CGRectZero configuration:conf];
[wk loadRequest:...];
複製代碼
WKWebViewConfiguration *conf = [WKWebViewConfiguration new];
WKWebView *wk = [[WKWebView alloc] initWithFrame:CGRectZero configuration:conf];
// 在初始化方法以後,設置 cookie
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithPropertie:...];
[[WKWebsiteDataStore defaultDataStore].httpCookieStore setCookie:cookie ...];
[wk loadRequest:...];
複製代碼
是否等待H5內容所有加載完成後纔開始渲染畫面,默認爲 NO
,若是設置爲 YES
,則 H5
在加載完成以前一直處於白屏狀態。
例如H5代碼:
// 在測試H5頁面尾巴處加入以下代碼,能夠查看區別。
<script type="text/javascript">
setTimeout(function(){
for(var i = 1; i<10000; i++)
{
alert(i);
}
})
</script>
複製代碼
不會覆蓋原來的請求頭重 User-Agent
的值屬性,在以後追加自定義的內容。
是否容許 AirPlay 投屏播放,默認容許
哪些媒體文件須要強制用戶進行手勢交互後才能播放。
該屬性將影響 H5
中 video
標籤的 autoplay 屬性
H5
中的 Video
標籤支持局部視頻播放,不會全屏視頻。Video
標籤的 playinline="true"
屬性,就能夠實現局部播放。A Boolean value indicating whether HTML5 videos may play picture-in-picture.
容許 H5
中 Video
標籤支持畫中畫模式,默認YES
可使用 H5
中的 JS 代碼實現畫中畫,video.requestPictureInPicture()
,iPhone 不支持,iPad 支持。
用戶能夠交互選擇web視圖中的內容的粒度級別.默認是 WKSelectionGranularityDynamic
暫時不知道用於什麼場景之下。
支持識別HTML的中字符信息:
UIDataDetectorTypePhoneNumber // 手機號
UIDataDetectorTypeLink // 網頁地址
UIDataDetectorTypeAddress // 郵件地址
UIDataDetectorTypeCalendarEvent // 格式化爲日曆事件的信息
UIDataDetectorTypeShipmentTrackingNumber // 快遞包裹信息
UIDataDetectorTypeFlightNumber // 航班號信息
UIDataDetectorTypeLookupSuggestion // 用戶可能要查找的信息
UIDataDetectorTypeNone // 默認,不檢測
UIDataDetectorTypeAll // 識別所有信息
複製代碼
默認爲 UIDataDetectorTypeNone,開啓檢測會影響網頁渲染速度。
ignoresViewportScaleLimits
是否忽略頁面縮放限制,默認爲 NO。
和H5中的參數存在關聯:
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=0.5,user-scalable=yes" />
複製代碼
名稱 | ||||
---|---|---|---|---|
ignoresViewportScaleLimits | NO | NO | YES | YES |
user-scalable | yes | no | yes | NO |
結論 | 按照指定尺寸進行縮放 | 沒法進行縮放 | 任意放大 | 任意放大 |
- (void)setURLSchemeHandler:(nullable id <WKURLSchemeHandler>)urlSchemeHandler
forURLScheme:(NSString *)urlScheme API_AVAILABLE(macos(10.13), ios(11.0));
- (nullable id <WKURLSchemeHandler>)urlSchemeHandlerForURLScheme:(NSString *)urlScheme API_AVAILABLE(macos(10.13), ios(11.0));
複製代碼
咱們能夠經過上述方法對 WKWebView 進行自定義協議攔截,沒法攔截 http
、https
、ws
、wss
、ftp
協議。
示例代碼:
[conf setURLSchemeHandler:[ViewSchemaHandler new] forURLScheme:@"h5"];
複製代碼
在 ViewSchemaHandler 實現協議中的內容
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask
{
// 在這裏能夠對同一資源進行本地緩存,無須要再次訪問。
NSMutableURLRequest *request = urlSchemeTask.request.mutableCopy;
request.URL = [NSURL URLWithString:[request.URL.absoluteString stringByReplacingOccurrencesOfString:@"h5://" withString:@"http://"]];
NSLog(@"%@", request.URL.absoluteURL);
NSURLSession* session = [NSURLSession sharedSession];
NSURLSessionTask* task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
[urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data];
[urlSchemeTask didFinish];
}];
[task resume];
}
- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask
{
// 當前urlSchemeTask因爲某些緣由提早結束了(會收到stopURLSchemeTask回調)
}
複製代碼
注意:
H5
前端全部想要攔截的js,css或者其餘網絡請求資源,須要將路徑寫成自適應協議路徑,例如以下寫法便可:<script type="text/javascript" src="//192.168.1.150:3206/7.3.7/js/libs/jquery.min.js" ></script>
複製代碼
H5
前端全部想要攔截的 Ajax 請求,須要將請求更改成相對或者絕對路徑,便可實現攔截$.ajax({
url:"/abcd"
});
複製代碼
能夠利用上述特性實現應用秒開。
能夠經過 decisionHandler
中的 decisionHandler
方法回調。
WKNavigationActionPolicyCancel
取消訪問WKNavigationActionPolicyAllow
容許繼續訪問,默認不實現爲該屬性示例代碼:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
// decisionHandler(WKNavigationActionPolicyCancel);
decisionHandler(WKNavigationActionPolicyAllow);
}
複製代碼
支持偏好設置,暫不理解。
是否容許響應回調,操做同 decidePolicyForNavigationAction
一致。
didStartProvisionalNavigation
發起首次請求會執行這個方法,屢次 302 重定向請求,該方法只會執行一次,發生 屢次 302 跳轉的時候,每次都會先執行 decidePolicyForNavigationAction
,若是這時候用戶選擇 cancel 操做,則 didReceiveServerRedirectForProvisionalNavigation
方法不會執行。
didReceiveServerRedirectForProvisionalNavigation,發生 302 重定向會走該方法
正常加載地址或者使用js
中的location.href
加載錯誤的地址發生失敗會走該回調。
// oc 代碼
[WKWebView loadRequest:] // 發生失敗會走該回調
// js代碼
location.href="http://abcd" // 發生失敗會走該回調
複製代碼
didCommitNavigation
,網絡請求加載完成後執行。
didFinishNavigation
完成 js,css,html 渲染後執行。
didFailNavigation
,例如:
window.open("http://abcd") // 發生失敗後會走該回調
複製代碼
didReceiveAuthenticationChallenge,能夠經過 completionHandler 來選擇對證書的操做,例如忽略證書。
/*
NSURLSessionAuthChallengeUseCredential = 0, 使用證書
NSURLSessionAuthChallengePerformDefaultHandling = 1, 忽略證書(默認的處理方式)
NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, 忽略書證, 並取消此次請求
NSURLSessionAuthChallengeRejectProtectionSpace = 3, 拒絕當前這一次, 下一次再詢問
*/
// NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential , card);
複製代碼
webViewWebContentProcessDidTerminate,webView 內容發生崩潰而終止,將會執行該回調方法。
UI代理方法,是H5部分UI操做和原生交互的代理方法,其中包括以下:
H5 中須要打開新窗口的操做,都會被這個方法攔截,例如
<a href="https://www.baidu.com" target="_blank" >打開新窗口</a>
window.open("https://www.baidu.com");
複製代碼
當H5執行 window.close()
方法,則會執行這個代理方法。
當H5執行 window.alert(...args)
方法,則會執行這個代理方法,須要注意:
completionHandler
這個 block
方法必須執行,不然會發生崩潰,彈出窗口若是使用 UIAlertController
做爲對接,則要考慮控制器是否存在,是否有併發的彈出窗操做,由於這些會致使 UIAlertController
彈不出來,最終可能在邏輯上形成 completionHandler
沒法執行致使崩潰,最好建議彈窗應該使用 UIView 設計。
當H5執行 window.confirm(...args)
,則會執行這個代理方法,注意事項同上。
當H5執行 window.prompt(...args)
,則會執行這個代理方法,注意事項同上。
contextMenu 的相關處理方法,暫時不理解在手機端有何用處。
WKWebView 中 H5 css 動畫失效的問題?
目前測試下來
[UIView snapshotViewAfterScreenUpdates:YES];
[UIView drawViewHierarchyInRect:CGRect afterScreenUpdates:YES];
這兩種方法在進行系統 UIView
的截圖操做時候而且將參數 afterScreenUpdates
設置爲 YES 的狀況下,最後 頻繁調用後會致使H5
中css
動畫失效,緣由不明。