史上最简单的TabbleView嵌套WebView

最近由于项目需求需要做一个tabbleview和webview嵌套的方法来实现上部显示新闻,下部显示评论的页面,其实这也是一个很常用的方式,打开网易或者头条看他们的新闻页基本都是这个路数,话不多说直接开撸。

史上最简单的TabbleView嵌套WebView_第1张图片
我叫杜甫,我很忙.jpg
对于项目所选用的webview,我义无反顾的选择WKWebview,对于它的好处,在这里就不赘述了。
//大概的加载顺序
- (void)viewDidLoad {
    [super viewDidLoad];
    [self makedata];
    [self setUpWenProgress];
    [self setUpWebView];
    [self setUpTableView];
    [self setUpBackButton];
}
再推出WKWebView之后,程序员就可以拿到真正的网页进度了,所以网页进度就要添加一个进度条展示出来
- (void)setUpWenProgress
{
    //    网页进度
    self.webProgress = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 50, swidth, 1)];
    self.webProgress.tintColor = [UIColor colorWithRed:255.0/255.0  green:215.0/255.0 blue:0 alpha:1.0];
    self.webProgress.trackTintColor = [UIColor whiteColor];
//    由于进度条是默认高度,通过以下方法改变高度
    self.webProgress.transform = CGAffineTransformMakeScale(1.0f, 2.0f);
    [self.view addSubview:self.webProgress];
}
//绑定之后用KVO进行监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"estimatedProgress"]) {
        self.webProgress.progress = self.newsWebview.estimatedProgress;
        if (self.webProgress.progress == 1) {
            /*
             *添加一个简单的动画,将progressView的Height变为1.4倍,在开始加载网页的代理中会恢复为1.5倍
             *动画时长0.25s,延时0.3s后开始动画
             *动画结束后将progressView隐藏
             */
            __weak typeof (self)weakSelf = self;
            [UIView animateWithDuration:0.25f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
                weakSelf.webProgress.transform = CGAffineTransformMakeScale(1.0f, 1.4f);
            } completion:^(BOOL finished) {
                weakSelf.webProgress.hidden = YES;
                
            }];
        }
    }else{
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}
//最后别忘了移除
对于WKWebView的基本设置
- (void)setUpWebView
{
    self.newsWebview = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, swidth, sheight)];
    self.newsWebview.scrollView.contentInset = UIEdgeInsetsMake(0, -1, 0, 2);
    self.newsWebview.navigationDelegate = self;
    self.newsWebview.UIDelegate = self;
// 防止webview的scrollView和tabbleview的scrollView一起滑动影响用户体验
    self.newsWebview.scrollView.scrollEnabled = NO;
    self.newsWebview.scrollView.showsVerticalScrollIndicator =NO;
    self.newsWebview.scrollView.showsHorizontalScrollIndicator=NO;
    self.newsWebview.backgroundColor=[UIColor clearColor];
    [self.newsWebview sizeToFit];
    self.newsWebview.opaque=NO;
    //    添加进度监控
    [self.newsWebview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];

    self.newsWebview.scrollView.bounces = NO;
    [self.newsWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
}
接下来就是添加页面的主角tabbleview
- (void)setUpTableView
{
    self.newsTabelview = [[UITableView alloc] init];
    self.newsTabelview.frame = CGRectMake(0, 0, swidth, sheight);
    self.newsTabelview.allowsSelection = NO;
    self.newsTabelview.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.newsTabelview.dataSource = self;
    self.newsTabelview.delegate = self;
    [self.view addSubview:self.newsTabelview];
    [self.view insertSubview:self.newsTabelview belowSubview:self.webProgress];
}

将网页加载到tabbleview的第一个cell里面,其余的cell加载新闻评论
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"webView"];
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"webView"];
        }
        [cell.contentView addSubview:self.newsWebview];
        return cell;
    }else{
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"comment"];
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"comment"];
        }
        cell.textLabel.text = self.dataArray[indexPath.row - 1];
        return cell;
    }
}
在网页加载完毕的时候,获取网页的高度
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
//当然下面的那句JS不是完全有效的,对于那些用JS拼接起来的网页高度就会失效
    [webView evaluateJavaScript:@"document.body.offsetHeight;" completionHandler:^(id string, NSError * _Nullable error) {
        self.webHeight = [string integerValue];
        self.newsWebview.frame = CGRectMake(0, 0, swidth, self.webHeight);
        WebViewLoadFinashi = YES;
        [self reloadView];
    }];
}
在刷新网页的时候重新给cell高度赋值
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        if (self.webHeight) {
            return self.webHeight;
        }else{
            return 0;
        }
    }else{
        return 50;
    }
}
这样看似基本上就完成了,但是动手做的时候会遇到一些坑,下面就列举下
  1. WebView划不动,iOS11能感觉出来他跟tabbleview直接存在间隙,iOS 10直接就是滑不动,解决办法
    self.newsWebview.scrollView.scrollEnabled = NO;

  1. WebView滑动的时候会有白块儿,好像是加载不完全的感觉,iOS 10上很明显,iOS 11稍微有点,解决办法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSArray *cells = self.newsTabelview.visibleCells;
    for (UITableViewCell *cell in cells) {
        if ([cell.reuseIdentifier isEqualToString:@"webView"]) {
            [self.newsWebview setNeedsLayout];
        }
    }
}

  1. 对于有些webview的高度通过上面的JS拿不到的话,建议你去掉拼接网页,然后求求你写网页的哥们让他给你写点页面布局JS然后嵌入到网页里面就好了。
// 在网页加载完的时候把写好的JS或者别的插入进去就好
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation

}

4.在退出页面的时候estimatedProgress不能释放的问题造成页面崩溃,iOS 11没问题,iOS 10上很明显

- (void)dealloc
{
    [self newsWebviewRelease];
}

/**
 退出的时候网页的代理置空
 */
- (void)newsWebviewRelease
{
    self.newsWebview.scrollView.delegate = nil;
    self.newsWebview.navigationDelegate = nil;
    self.newsWebview.UIDelegate = nil;
    if (self.newsWebview.isLoading) {
        [self.newsWebview stopLoading];
    }
    [self.newsWebview removeObserver:self forKeyPath:@"estimatedProgress"];
    [self.newsWebview removeFromSuperview];
    self.newsWebview = nil;
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
}

这样基本上就没问题了,接下来附上本文的demo。

你可能感兴趣的:(史上最简单的TabbleView嵌套WebView)