一般情況下在UITableView的header或cell中加載webview况褪,需要動態(tài)計算webview的內(nèi)容高度,然后刷新tableview更耻,那么接下來問題的重點就是如何準確的拿到webview的內(nèi)容高度了
webview加載分兩種:1测垛、加載靜態(tài)HTML,2酥夭、加載動態(tài)HTML赐纱。
兩者在高度計算上是有區(qū)別的,下面就針對這兩種進行討論熬北。
一疙描、加載動態(tài)HTML
[ 思路1:從WKWebview的加載完成代理方法中著手]
代碼如下:
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result,NSError * _Nullable error) {
//1.獲取頁面高度,并重新計算webview的高度
//2.緩存頁面高度
//3.tableview update
}];
}
但是讶隐,很可惜,這里獲取的高度有時不精確起胰,于是,采用了另一種方法。
[ 思路2:使用KVO監(jiān)聽webView.scrollView的contentSize]
code:
cell的方法
- cell初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UIView *superView = self.contentView;
superView.backgroundColor = [UIColor blueColor];
WKWebView *webView = [[WKWebView alloc] initWithFrame:superView.bounds];
webView.scrollView.scrollEnabled = NO;//禁用webView滑動
webView.scrollView.userInteractionEnabled = NO;
//自適應(yīng)寬高效五,這句要加
webView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
// webView.navigationDelegate = self;
_webView = webView;
[superView addSubview:_webView];
//監(jiān)聽webView.scrollView的contentSize屬性
[_webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
return self;
}
- KVO監(jiān)聽處理
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"contentSize"]) {
__weak typeof(self) weakSelf = self;
//執(zhí)行js方法"document.body.offsetHeight" 地消,獲取webview內(nèi)容高度
[_webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
CGFloat contentHeight = [result floatValue];
if (weakSelf.webHeightChangedCallback) {
weakSelf.webHeightChangedCallback(contentHeight);
}
}];
}
}
- 移除kvo監(jiān)聽
- (void)dealloc
{
[_webView.scrollView removeObserver:self forKeyPath:@"contentSize"];
}
- tableview部分
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1) {
return _webHeight;//web高度,全局屬性
}
return 44;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1) {
WebTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(WebTableViewCell.class)];
if (!cell) {
cell = [[WebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass(WebTableViewCell.class)];
}
__weak typeof(self) weakSelf = self;
cell.webHeightChangedCallback = ^(CGFloat webHeight) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf->_webHeight < webHeight) {//當緩存的高度小于返回的高度時畏妖,更新緩存高度脉执,刷新tableview
strongSelf->_webHeight = webHeight;
[weakSelf.tableView beginUpdates];
[weakSelf.tableView endUpdates];
}
};
return cell;
}
return nil;
}
//去除web頁底部空白
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { // 判斷webView所在的cell是否可見,如果可見就layout
NSArray *cells = self.tableView.visibleCells;
for (UITableViewCell *cell in cells) {
if ([cell isKindOfClass:[WebTableViewCell class]]) {
WebTableViewCell *webCell = (WebTableViewCell *)cell;
[webCell.webView setNeedsLayout];
}
}
}
二戒劫、加載靜態(tài)HTML
和動態(tài)HTML類似半夷,需要監(jiān)聽高度
[_webView.scrollView addObserver:self forKeyPath:contentSizeKey options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
懶加載webview
- (WKWebView *)webView{
if (!_webView) {
//以下代碼適配大小
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
[wkUController addUserScript:wkUScript];
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.userContentController = wkUController;
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, ScreenW, 0) configuration:wkWebConfig];
//禁用scrollview的交互
_webView.scrollView.scrollEnabled = NO;
_webView.scrollView.userInteractionEnabled = NO;
_webView.navigationDelegate = self;
_webView.scrollView.delegate = self;
[_webView addSubview:self.indicatorView];
//高度監(jiān)聽
[_webView.scrollView addObserver:self forKeyPath:contentSizeKey options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
[self.contentView addSubview:_webView];
}
return _webView;
}
加載HTML
- (void)configuration:(NSString *)html{
if (html.length > 0 && ([html containsString:@"http"] || [html containsString:@"https"])) {
[self.webView loadHTMLString:html baseURL:nil];
}
}
禁止縮放
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return nil;
}
//監(jiān)聽移除
- (void)removeObserverForWebViewContentSize {
[_webView.scrollView removeObserver:self forKeyPath:contentSizeKey];
}
//KVO獲取高度
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:contentSizeKey]) {
CGFloat height = self.webView.scrollView.contentSize.height;
id old = change[NSKeyValueChangeOldKey];
id new = change[NSKeyValueChangeNewKey];
// NSLog(@"height-->%f->old-->%@-->new-->%@",height,old,new);
if (height > 0) {
if (_wkWebViewHeight) {
_webView.frame = CGRectMake(0, 0, ScreenW, height);
self.indicatorView.center = _webView.center;
self.wkWebViewHeight(height);
}
}
if ([old isEqual:new]) {
[self removeObserverForWebViewContentSize];//重點 : 高度回調(diào)后把監(jiān)聽移除,不然會重復(fù)走這段代碼
self.loadFinished();
}
}
}
//當webview加載完成迅细,再次更新高度
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"加載結(jié)束didFinishNavigation");
[self.indicatorView stopAnimating];
CGFloat webH = webView.scrollView.contentSize.height;
_webView.frame = CGRectMake(0, 0, ScreenW, webH);
if (_wkWebViewHeight) {
self.wkWebViewHeight(webH);
self.loadFinished();
}
}
controller里更加獲取的高度刷新tableview
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
···
cell.wkWebViewHeight = ^(CGFloat height) {
if (weakSelf.webViewH != height) {
weakSelf.webViewH = height;
[weakSelf.tableView beginUpdates];
[weakSelf.tableView endUpdates];
}
};
cell.loadFinished = ^{
[weakSelf.tableView beginUpdates];
[weakSelf.tableView endUpdates];
};
···
}
以上僅為本人在開發(fā)中遇到的問題巫橄,并嘗試解決,如有問題茵典,歡迎指正湘换,謝謝!