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.javascript
WKWebVIew是iOS8新出的API,旨在替代原有的UIWebView,相對於UIWebView,WKWebView有着更爲強大性能和豐富的API。在項目開發過程當中,我也更傾向於用WKWebView,但在使用過程當中也遇到許多的問題。html
最近接觸使用網頁視圖比較多,本身在tableView和scrollView中嵌套網頁視圖,在獲取網頁視圖高度遇到過很多的坑,例如高度不許確、底部留白斷層,滾動一直獲取高度問題。如今項目中使用的網頁視圖基本都替換成了WKWebView,關於WKWebView使用的一些坑,我強烈推薦一篇博客WKWebView 那些坑,但願使用WKWebView能少走一些彎路,少踩一些坑。好了,話很少說了,我將項目中獲取網頁視圖高度實際經驗分享給你們,但願對你有所幫助,下面開始介紹吧!java
這種方式獲取的高度較爲準確,但要注意表格中屢次回調高度的問題。ios
#pragma mark ------ < Private Method > ------
#pragma mark
- (void)addWebViewObserver {
[self.wkWebView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
複製代碼
#pragma mark ------ < KVO > ------
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
/** < 法2 > */
/** < loading:防止滾動一直刷新,出現閃屏 > */
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
,網頁加載完成經過JS獲取網頁內容高度,但這種方式不必定就是最真實的高度,這時候可能網頁內容還未加載完成,但以實際狀況爲準。git
/** < 法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];
}
複製代碼
第三種一般是接口返回HTMLString,而後本身在APP客戶端成網頁html、head、body這些標籤,在合適的位置加入如下js代碼:github
<script type=\"text/javascript\">\
window.onload = function() {\
window.location.href = \"ready://\" + document.body.scrollHeight;\
}\
</script>
複製代碼
而後藉助WKWebView代理方法,就能準確得到網頁高度:web
- (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中是看不到效果的,有興趣的朋友能夠本身拼接網頁HTMLString測試效果。我也貼一個我在項目中添加以上代碼片斷的位置吧:objective-c
<!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>
//接口返回網頁內容,拼接在這裏
</body>
</html>
複製代碼
#pragma mark ------ < UIScrollViewDeltegate > ------
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
/** < 解決web白屏問題 > */
/** < 須要調用私有API:_updateVisibleContentRects > */
[self.wkWebView setNeedsLayout];
}
複製代碼
最新demo請戳:WKWebViewAutoHeightapp