iOS精準獲取webView內容高度,自適應高度(cell篇)

在這個問題卡了很久,最終參照了
http://www.itdecent.cn/p/6bbcc438b188 作者:臭碼農 的做法搞定了,做一下記錄 加強一下自己的印象和理解,也為同樣是cell里有webView的 同學提供一個例子.

一.問題原因

發(fā)現(xiàn)問題首先要確定問題的根本原因在哪里,上面文章說的已經很具體,所以就不再多此一舉。

二.具體代碼

cell中的代碼展示如下:(只展示了關鍵性的代碼以及解決cell復用問題的思路)

.h代碼
#import <UIKit/UIKit.h>

@interface JQTHomePageTipsItemsWithHtmlStrTypeCell : UITableViewCell
typedef void(^WebViewHeightChangedBlock)(int height);
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@property (nonatomic, strong) JQTActivityExplainItemModel *activityExplainItemModel;
@property (nonatomic, strong) WebViewHeightChangedBlock webViewHeightChanged;


@end
.m代碼
#import "JQTHomePageTipsItemsWithHtmlStrTypeCell.h"
@interface JQTHomePageTipsItemsWithHtmlStrTypeCell()<UIWebViewDelegate>
@end
@implementation JQTHomePageTipsItemsWithHtmlStrTypeCell

- (void)awakeFromNib {
    [super awakeFromNib];
    self.webView.delegate = self;
    self.webView.scrollView.scrollEnabled = NO;
    self.webView.backgroundColor = [UIColor clearColor];
}
- (void)setActivityExplainItemModel:(JQTActivityExplainItemModel *)activityExplainItemModel {

    _activityExplainItemModel = activityExplainItemModel;
    NSMutableString *htmlString =xxx;
    //這里應該為htmlString的代碼
    self.webView.frame = CGRectMake(0, 0, 320, 1);
    [self.webView loadHTMLString:htmlString baseURL:nil];
    
    //監(jiān)聽scrollView contentSize 變化
    [_webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
-(void)layoutSubviews
{
    [super layoutSubviews];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
        NSLog(@"-----------------webViewDidFinishLoad");
    if (webView.isLoading) {
        return;
    }
    CGFloat webViewHeightFromScrollContentSize =[webView.scrollView contentSize].height;
    CGRect newFrame = webView.frame;
    newFrame.size.height = webViewHeightFromScrollContentSize;
    webView.frame = newFrame;
    
    //下面這兩行是去掉不必要的webview效果的(選中,放大鏡)
    [self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    
    [self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    
    NSLog(@"webViewload出錯了!");
}

監(jiān)聽contentSize方法(重點)
//監(jiān)聽方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"contentSize"]) {

        CGSize fitSize = [_webView sizeThatFits:CGSizeZero];
//        NSLog(@"webview fitSize:%@",NSStringFromCGSize(fitSize));
        self.webView.frame = CGRectMake(0, 0, fitSize.width, fitSize.height);
        
        if(self.webViewHeightChanged){
            self.webViewHeightChanged(self.webView.frame.size.height);
        }
    }
}

//這里別忘了在dealloc理移除監(jiān)聽
- (void)dealloc {
    NSLog(@"webView ---------dealloc");
    [self.webView.scrollView removeObserver:self
                                 forKeyPath:@"contentSize" context:nil];
}
寫到這里,需要思考的有以下兩點:
  1. 監(jiān)聽contentSize方法 一旦scrollView的contentSize發(fā)生改變,這個方法就會走,那么他會不會無限調用呢,所以我就趕緊打印看了看,結果如下

    2017-06-21 17:02:55.717 JQTWander[5901:130422] webview fitSize:{540, 226}

    2017-06-21 17:02:55.718 JQTWander[5901:130422] webview fitSize:{540, 226}

    只重復一次的原因當然是因為上述方法并沒有一直改變contentsize的值,而是獲取了一次以后就固定了,所以就會多調用一次

  2. 如何完美的解決cell復用問題

    我首先想到的是棄用復用池,因為我的項目里這是個活動詳情界面,整個頁面下來cell也沒幾個,所以控制器代碼如下:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        if (self.htmlCell==nil) {
            self.htmlCell = [[Bundle loadNibNamed:@"JQTHomePageTipsItemsWithHtmlStrTypeCell" owner:self options:nil] lastObject];
          
              [self requestData];
      }
      
      - (void)requestData{
        //這里在請求成功獲取到對應model以后
                    [self reloadWebView];
      }
      
      - (void)reloadWebView {
        
         self.webViewheight = -1;
        self.webViewheightSecound = - 1;
        self.webViewheightThird = - 1;
        self.webViewheightFourth = - 1;
        
        @weakify(self)
        self.htmlCell.activityExplainItemModel = activityExplainItemModel;
        self.htmlCell.webViewHeightChanged = ^(int height){
            @strongify(self)
            BOOL needReload=NO;
            if(self.webViewheight<0) needReload=YES;
            self.webViewheight =height;
            NSLog(@"callback --------webViewheight  %d",height);
        //此處needReload有點不嚴謹,根據(jù)需求可以考慮暫時去掉,因為要考慮到多次加載還未獲取到最終高度,所以只能多刷新幾次tableView
            if (needReload) {
                [self.tableView reloadData];
            }
        };
      }
    
之后是tableView代理方法中的代碼

都是直接return

if (indexPath.section == 3) {
                       return self.htmlCell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
      if (indexPath.section == 3) {
        //webViewheight在webView的scrollView的contentsize的監(jiān)聽方法里通過block回調已經提前拿到了
        return self.webViewheight;
}
}

這樣就完美解決了復用問題。

以上屬于本人原創(chuàng),若有雷同屬巧合,如有錯誤望指正,轉載請標明來源和作者。by:鏡花水月cy

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容