这个方案是 webView 作为 TableView 的 TableHeaderView 或者 TableView 的一个 Cell, 然后根据网页的高度动态的更新 TableHeaderView 和 Cell 的高度, 这个方案逻辑上最简单, 也最容易实现, 而且滑动效果也比较好.
然而在实际应用中发现如果资讯内容很长而且带有大量图片和 GIf 图片的时候, APP 内存占用会暴增, 有被系统杀掉的风险. 但是在单纯的使用 WebView 的时候内存占用不会那么大, WebView 会根据自身视口的大小动态渲染 html 内容, 不会一次性的渲染素有的 HTML 内容. 这个方案只是简单的将 WebView 的大小更新为 HTML 的实际大小, WebView 将会一次性的渲染所有的 HTML 内容, 因此直接使用这种方案会有内存占用暴增的风险.
我们看下业界内主流的实现方案:
1, 网易新闻:
- TableViewView.height = scrollView.height
- ;
- WebView.height = WebView.contentSize.height
- ;
- TableViewView.height = TableViewView.contentSize.height
- ;
- #import "ViewController.h"
- #import <WebKit/WebKit.h>
- #import "UIView+HSKit.h"
- @interface ViewController ()<UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate>
- @property (nonatomic, strong) WKWebView *webView;
- @property (nonatomic, strong) UITableView *tableView;
- @property (nonatomic, strong) UIScrollView *containerScrollView;
- @property (nonatomic, strong) UIView *contentView;
- @end
- @implementation ViewController{
- CGFloat _lastWebViewContentHeight;
- CGFloat _lastTableViewContentHeight;
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- [self initValue];
- [self initView];
- NSString *path = @"https://www.jianshu.com/p/f31e39d3ce41";
- NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:path]];
- request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
- [self.webView loadRequest:request];
- [self addObservers];
- }
- - (void)dealloc{
- [self removeObservers];
- }
- - (void)didReceiveMemoryWarning {
- [super didReceiveMemoryWarning];
- }
- - (void)initValue{
- _lastWebViewContentHeight = 0;
- _lastTableViewContentHeight = 0;
- }
- - (void)initView{
- [self.contentView addSubview:self.webView];
- [self.contentView addSubview:self.tableView];
- [self.view addSubview:self.containerScrollView];
- [self.containerScrollView addSubview:self.contentView];
- self.contentView.frame = CGRectMake(0, 0, self.view.width, self.view.height * 2);
- self.webView.top = 0;
- self.webView.height = self.view.height;
- self.tableView.top = self.webView.bottom;
- }
- #pragma mark - Observers
- - (void)addObservers{
- [self.webView addObserver:self forKeyPath:@"scrollView.contentSize" options:NSKeyValueObservingOptionNew context:nil];
- [self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
- }
- - (void)removeObservers{
- [self.webView removeObserver:self forKeyPath:@"scrollView.contentSize"];
- [self.tableView removeObserver:self forKeyPath:@"contentSize"];
- }
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
- if (object == _webView) {
- if ([keyPath isEqualToString:@"scrollView.contentSize"]) {
- [self updateContainerScrollViewContentSize:0 webViewContentHeight:0];
- }
- }else if(object == _tableView) {
- if ([keyPath isEqualToString:@"contentSize"]) {
- [self updateContainerScrollViewContentSize:0 webViewContentHeight:0];
- }
- }
- }
- - (void)updateContainerScrollViewContentSize:(NSInteger)flag webViewContentHeight:(CGFloat)inWebViewContentHeight{
- CGFloat webViewContentHeight = flag==1 ?inWebViewContentHeight :self.webView.scrollView.contentSize.height;
- CGFloat tableViewContentHeight = self.tableView.contentSize.height;
- if (webViewContentHeight == _lastWebViewContentHeight && tableViewContentHeight == _lastTableViewContentHeight) {
- return;
- }
- _lastWebViewContentHeight = webViewContentHeight;
- _lastTableViewContentHeight = tableViewContentHeight;
- self.containerScrollView.contentSize = CGSizeMake(self.view.width, webViewContentHeight + tableViewContentHeight);
- CGFloat webViewHeight = (webViewContentHeight < self.view.height) ?webViewContentHeight :self.view.height ;
- CGFloat tableViewHeight = tableViewContentHeight < self.view.height ?tableViewContentHeight :self.view.height;
- self.webView.height = webViewHeight <= 0.1 ?self.view.height :webViewHeight;
- self.contentView.height = webViewHeight + tableViewHeight;
- self.tableView.height = tableViewHeight;
- self.tableView.top = self.webView.bottom;
- }
- #pragma mark - UIScrollViewDelegate
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
- if (_containerScrollView != scrollView) {
- return;
- }
- CGFloat offsetY = scrollView.contentOffset.y;
- CGFloat webViewHeight = self.webView.height;
- CGFloat tableViewHeight = self.tableView.height;
- CGFloat webViewContentHeight = self.webView.scrollView.contentSize.height;
- CGFloat tableViewContentHeight = self.tableView.contentSize.height;
- if (offsetY <= 0) {
- self.contentView.top = 0;
- self.webView.scrollView.contentOffset = CGPointZero;
- self.tableView.contentOffset = CGPointZero;
- }else if(offsetY < webViewContentHeight - webViewHeight){
- self.webView.scrollView.contentOffset = CGPointMake(0, offsetY);
- self.contentView.top = offsetY;
- }else if(offsetY < webViewContentHeight){
- self.tableView.contentOffset = CGPointZero;
- self.webView.scrollView.contentOffset = CGPointMake(0, webViewContentHeight - webViewHeight);
- }else if(offsetY < webViewContentHeight + tableViewContentHeight - tableViewHeight){
- self.contentView.top = offsetY - webViewHeight;
- self.tableView.contentOffset = CGPointMake(0, offsetY - webViewContentHeight);
- self.webView.scrollView.contentOffset = CGPointMake(0, webViewContentHeight - webViewHeight);
- }else if(offsetY <= webViewContentHeight + tableViewContentHeight ){
- self.webView.scrollView.contentOffset = CGPointMake(0, webViewContentHeight - webViewHeight);
- self.tableView.contentOffset = CGPointMake(0, tableViewContentHeight - tableViewHeight);
- self.contentView.top = self.containerScrollView.contentSize.height - self.contentView.height;
- }else {
- //do nothing
- NSLog(@"do nothing");
- }
- }
- #pragma mark - UITableViewDataSouce
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
- return 10;
- }
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
- return 200;
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
- if (cell == nil) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
- cell.backgroundColor = [UIColor redColor];
- }
- cell.textLabel.text = @(indexPath.row).stringValue;
- return cell;
- }
- #pragma mark - private
- - (WKWebView *)webView{
- if (_webView == nil) {
- WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
- _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
- _webView.scrollView.scrollEnabled = NO;
- _webView.navigationDelegate = self;
- }
- return _webView;
- }
- - (UITableView *)tableView{
- if (_tableView == nil) {
- _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
- _tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
- _tableView.delegate = self;
- _tableView.dataSource = self;
- _tableView.tableFooterView = [UIView new];
- _tableView.scrollEnabled = NO;
- }
- return _tableView;
- }
- - (UIScrollView *)containerScrollView{
- if (_containerScrollView == nil) {
- _containerScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
- _containerScrollView.delegate = self;
- _containerScrollView.alwaysBounceVertical = YES;
- }
- return _containerScrollView;
- }
- - (UIView *)contentView{
- if (_contentView == nil) {
- _contentView = [[UIView alloc] init];
- }
- return _contentView;
- }
- @end
来源: http://www.jianshu.com/p/3721d736cf68