在这个问题卡了很久,最终参照了
http://www.jianshu.com/p/6bbcc438b188 作者:臭码农 的做法搞定了,做一下记录 加强一下自己的印象和理解,也为同样是cell里有webView的 同学提供一个例子.
一.问题原因
发现问题首先要确定问题的根本原因在哪里,上面文章说的已经很具体,所以就不再多此一举。
二.具体代码
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];
//监听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出错了!");
}
监听contentSize方法(重点)
//监听方法
- (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理移除监听
- (void)dealloc {
NSLog(@"webView ---------dealloc");
[self.webView.scrollView removeObserver:self
forKeyPath:@"contentSize" context:nil];
}
写到这里,需要思考的有以下两点:
-
监听contentSize方法 一旦scrollView的contentSize发生改变,这个方法就会走,那么他会不会无限调用呢,所以我就赶紧打印看了看,结果如下
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有点不严谨,根据需求可以考虑暂时去掉,因为要考虑到多次加载还未获取到最终高度,所以只能多刷新几次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的监听方法里通过block回调已经提前拿到了
return self.webViewheight;
}
}
这样就完美解决了复用问题。
以上属于本人原创,若有雷同属巧合,如有错误望指正,转载请标明来源和作者。by:镜花水月cy