史上最简单的TabbleView嵌套WebView

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

我叫杜甫,我很忙.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<NSString *,id> *)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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,303评论 4 61
  • 亲爱的自己,回首过去三十年的生涯,你无数次站在命运的交叉口,徘徊犹豫又坚定不移,彷徨无助又咬牙坚持,终于成为了现在...
    史丽芬阅读 277评论 1 6
  • 在快速发展的创业公司,做PR和BD的伙伴通常都会为寻找合适的合作伙伴苦恼,即使手里握着大把银子,也要砸对地方砸出花...
    王颜森阅读 1,917评论 0 2
  • 在我们身边,总有这么一群人,他们一动筷子吃饭,还没有吃两口就会大汗淋漓。通常来说,有的是人中冒汗,有的是额头冒汗,...
    魏文花阅读 335评论 0 0
  • 风拂绿墙生妩媚, 光影屋瓦点斑斓。 心无俗事听鸟鸣, 闲坐青苔静读禅。
    明续阅读 271评论 0 2