WKWebView高度自適應(yīng)三種方式

一、前言

Important
Starting in iOS 8.0 and OS X 10.10, use WKWebView to add web content to your app. Do not use UIWebView or WebView.

WKWebVIew是iOS8新出的API,旨在替代原有的UIWebView,相對(duì)于UIWebView,WKWebView有著更為強(qiáng)大性能和豐富的API。在項(xiàng)目開發(fā)過程中,我也更傾向于用WKWebView,但在使用過程中也遇到許多的問題。
最近接觸使用網(wǎng)頁視圖比較多,自己在tableView和scrollView中嵌套網(wǎng)頁視圖,在獲取網(wǎng)頁視圖高度遇到過不少的坑,例如高度不準(zhǔn)確、底部留白斷層,滾動(dòng)一直獲取高度問題?,F(xiàn)在項(xiàng)目中使用的網(wǎng)頁視圖基本都替換成了WKWebView,關(guān)于WKWebView使用的一些坑,我強(qiáng)烈推薦一篇博客WKWebView 那些坑,希望使用WKWebView能少走一些彎路,少踩一些坑。好了,話不多說了,我將項(xiàng)目中獲取網(wǎng)頁視圖高度實(shí)際經(jīng)驗(yàn)分享給大家,希望對(duì)你有所幫助,下面開始介紹吧!

二、目錄

  • 通過KVO的方式
  • 通過代理的方式
  • 通過注入JS的方式,添加網(wǎng)頁加載完成回調(diào)獲取

通過KVO的方式

這種方式獲取的高度較為準(zhǔn)確,但要注意表格中多次回調(diào)高度的問題。

  • 添加監(jiān)聽者
    #pragma mark ------ < Private Method > ------
    #pragma mark
    - (void)addWebViewObserver {
        [self.wkWebView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
    }
    
  • 監(jiān)聽高度變化
    #pragma mark ------ < KVO > ------
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
        /**  < 法2 >  */
        /**  < loading:防止?jié)L動(dòng)一直刷新,出現(xiàn)閃屏 >  */
        if ([keyPath isEqualToString:@"contentSize"]) {
            CGRect webFrame = self.wkWebView.frame;
            webFrame.size.height = self.wkWebView.scrollView.contentSize.height;
            self.wkWebView.frame = webFrame;
            [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3 inSection:0], nil] withRowAnimation:UITableViewRowAnimationNone];
        }
    }
    
  • 移除觀察者
  • - (void)removeWebViewObserver {
        [self.wkWebView.scrollView removeObserver:self forKeyPath:@"contentSize"];
    }
    

通過代理的方式

這種方法通過WKNavigationDelegate代理方法- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation,網(wǎng)頁加載完成通過JS獲取網(wǎng)頁內(nèi)容高度,但這種方式不一定就是最真實(shí)的高度,這時(shí)候可能網(wǎng)頁內(nèi)容還未加載完成,但以實(shí)際情況為準(zhǔn)。

/**  < 法2 >  */
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    //document.body.offsetHeight
    //document.body.scrollHeight
    //document.body.clientHeight
    [webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
       CGFloat documentHeight = [result doubleValue];
        CGRect webFrame = webView.frame;
        webFrame.size.height = documentHeight;
        webView.frame = webFrame;
        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3 inSection:0], nil] withRowAnimation:UITableViewRowAnimationNone];
    }];

    
//    CGRect webFrame = self.wkWebView.frame;
//    CGFloat contentHeight = webView.scrollView.contentSize.height;
//    webFrame.size.height = contentHeight;
//    webView.frame = webFrame;
//    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3 inSection:0], nil] withRowAnimation:UITableViewRowAnimationNone];
}

通過注入JS的方式,添加網(wǎng)頁加載完成回調(diào)獲取

第三種通常是接口返回HTMLString,然后自己在APP客戶端成網(wǎng)頁html、head、body這些標(biāo)簽,在合適的位置加入以下js代碼:

<script type=\"text/javascript\">\
        window.onload = function() {\
        window.location.href = \"ready://\" + document.body.scrollHeight;\
        }\
 </script>

然后借助WKWebView代理方法,就能準(zhǔn)確獲得網(wǎng)頁高度:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if (navigationAction.navigationType == WKNavigationTypeOther) {
        if ([[[navigationAction.request URL] scheme] isEqualToString:@"ready"]) {
            float contentHeight = [[[navigationAction.request URL] host] floatValue];
            CGRect webFrame = self.wkWebView.frame;
            webFrame.size.height = contentHeight;
            webView.frame = webFrame;
            
            NSLog(@"onload = %f",contentHeight);
            
            [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3 inSection:0], nil] withRowAnimation:UITableViewRowAnimationNone];
            
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

第三種方法在我寫的demo中是看不到效果的,有興趣的朋友可以自己拼接網(wǎng)頁HTMLString測試效果。我也貼一個(gè)我在項(xiàng)目中添加以上代碼片段的位置吧:

<!DOCTYPE html>
<html>

<meta charset=\"utf-8\">

<meta name=\"viewport\"content=\"width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\">\
    <title></title>
    
<head>

<script type=\"text/javascript\">\
     window.onload = function() {\
     window.location.href = \"ready://\" + document.body.scrollHeight;\
     }\
     </script>

</head>

<body>
    
//接口返回網(wǎng)頁內(nèi)容,拼接在這里
    
</body>

</html>

三、問題解決

  • 解決web斷層問題:WKWebView刷新機(jī)制小探
    #pragma mark ------ < UIScrollViewDeltegate > ------
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        /**  < 解決web白屏問題 >  */
        /**  < 需要調(diào)用私有API:_updateVisibleContentRects >  */
        [self.wkWebView setNeedsLayout];
    }
    

四、demo

最新demo請(qǐng)戳:WKWebViewAutoHeight

五、參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容