在這個問題卡了很久,最終參照了
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];
}
寫到這里,需要思考的有以下兩點:
-
監(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的值,而是獲取了一次以后就固定了,所以就會多調用一次
-
如何完美的解決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