細聊WKWebView加載URL

鑒于UIWebView的內存問題,新項目選擇了WKWebView來加載URL詳情頁面,本文將圍繞“加載URL詳情頁面,并確保內部鏈接正常跳轉”的需求,細聊開發過程中遇到的問題。(注:本文不涉及js交互、緩存相關的內容)

一、WKWebView的基本使用

1、加載指定的URL
- (void)gotoWebViewWithUrl:(NSString *)Url
{
    WKWebView *webview = [[WKWebView alloc]initWithFrame:self.view.bounds];
    [webview loadRequest:[NSURL URLWithString: Url];
}
2、代理

(1) WKNavigationDelegate

// 準備加載頁面
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
// 內容開始加載
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
// 頁面加載完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
// 頁面加載失敗
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;

// 收到服務器重定向請求
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
// 在收到響應開始加載后,決定是否跳轉
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
// 在請求開始加載之前,決定是否跳轉
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

(2) WKUIDelegate
?JS交互時會用到這個代理,本文討論的需求不涉及JS交互,所以這里不在贅述。

二、問題及解決方案

1、黑屏閃現

問題描述: 執行[webview loadRequest:]加載URL頁面時,偶爾會有黑屏閃現的現象。
?解決方案: 在初始化webView時,加載一個空白頁面。

// 加載空白頁
- (void)loadBlankHtml
{
    static NSString *blankHtmlStr = @"<!DOCTYPE html>\
    <html lang=\"en\">\
      <head>\
        <meta charset=\"UTF-8\">\
        <title>Document</title>\
        <style>body{background-color: #111111;}</style>\
      </head>\
      <body></body>\
    </html>";
    [self.webView loadHTMLString:blankHtmlStr baseURL:[NSURL URLWithString:kAboutBlank]];
}
2、加載進度、加載超時問題

問題描述:
??點擊webView的某個鏈接跳轉至新的頁面時,會異步的觸發N個請求(多次觸發回調1)來獲取頁面的多個模塊數據,其中某些請求可能不會響應(不會觸發回調2),某些請求可能不會有成功、失敗的回調。
??所以,無法通過監聽請求的開始、結束獲取加載進度,判斷加載超時。

 // 回調1: 在請求開始加載之前,決定是否跳轉
 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
 // 回調2: 在收到響應開始加載后,決定是否跳轉
 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;

解決方案:請求觸發回調2方法后才算真正的開始,展示進度條、啟動超時檢測,請求有成功、失敗的返回時,隱藏進度條、停止超時檢測。

// 在收到響應開始加載后,決定是否跳轉
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
    if (NO == self.progressView.hidden) {
      [self restartOutTimer];
      self.progressView.hidden = hide;
    }
    if (decisionHandler) {
      decisionHandler(WKNavigationResponsePolicyAllow);
    }
}
3、加載超時處理

問題描述:
?加載超時或沒有網絡時,需要在頁面中告知用戶,同時不影響現有的webView頁面層級關系。(例如,加載頁面后斷網,點擊頁面內鏈接,需要告知用戶沒有網絡,用戶可以通過返回按鈕返回到剛才的頁面)
?解決方案: 加載本地html頁面。

// 在請求開始加載之前,決定是否跳轉
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSString* requestUrl = [navigationAction.request.URL absoluteString];
    // 沒有網絡時,展示本地url頁面
    if (self.curNetworkStatus == NetworkNotReachable &&
    navigationAction.navigationType != WKNavigationTypeBackForward) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"NoNetwork" ofType:@"html"];
        if (![requestUrl isEqualToString:self.rootUrl]) {
            [self loadFileURLWithPath:path];
        } else {
            [self loadHTMLStringWithPath:path];
       }
       decisionHandler(WKNavigationActionPolicyCancel);
    }
}
3、跳轉App Store問題

WKWebView不支持https://itunes.apple.com/cn/app/id******這樣的鏈接跳轉App Store,需要做出如下的處理才能正常跳轉。

// 在請求開始加載之前調用,決定是否跳轉
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    // itunes跳轉鏈接需要單獨處理
    if ([[navigationAction.request.URL host] isEqualToString:@"itunes.apple.com"] &&
        [[UIApplication sharedApplication] openURL:navigationAction.request.URL]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容