使用場(chǎng)景:
tableView 的 cell嵌套webView<webView加載一般是加載一個(gè)靜態(tài)網(wǎng)頁(yè),或者加載一段html片段>的時(shí)候,需要獲取webView的內(nèi)容的高度,然后計(jì)算相應(yīng)的cell的高度,進(jìn)而展示一些豐富的富文本之類的東西,是期中的一個(gè)使用場(chǎng)景。當(dāng)然可能還有其他的使用場(chǎng)景。
下面說一下期中的兩個(gè)小坑,或者說注意事項(xiàng)。
獲取webView高度的方法
獲取webView的高度的方法是在webView的代理中進(jìn)行的,當(dāng)webView加載完畢之后,webView的代理中可以獲取相關(guān)的webView的高度
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//獲取到webview的高度
CGFloat webViewHeight1 = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
CGFloat webViewHeight2 = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];
CGFloat webViewHeight3 = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.clientHeight"] floatValue];
NSLog(@"webViewHeight1 == %f",webViewHeight1);
NSLog(@"webViewHeight2 == %f",webViewHeight2);
NSLog(@"webViewHeight3 == %f",webViewHeight3);
webView.frame = CGRectMake(webView.frame.origin.x,webView.frame.origin.y, kScreenWidth, webViewHeight1);
// 獲取完畢之后以通知的形式,或者回調(diào)的形式通知tableView刷新
}
使用前提:
- (UIWebView *)myWebView
{
if (_myWebView == nil) {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 0)];
webView.delegate = self;
webView.scrollView.scrollEnabled = NO;
_myWebView = webView;
}
return _myWebView;
}
1、webView設(shè)置相關(guān)代理
2、webView禁止?jié)L動(dòng)
3、設(shè)置plist文件相關(guān)設(shè)置
但是計(jì)算完畢之后你會(huì)發(fā)現(xiàn)webView獲取的高度不準(zhǔn)確。
計(jì)算結(jié)果如下:
可以看到,webView的高度偏大。
第一個(gè)小坑出現(xiàn)了,那就是,webView初始化的時(shí)候高度不能設(shè)置為0
但是不知道為啥,有知道的請(qǐng)不吝賜教。
#pragma mark- set
- (UIWebView *)myWebView
{
if (_myWebView == nil) {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 1)];
webView.scrollView.scrollEnabled = NO;
webView.delegate = self;
_myWebView = webView;
}
return _myWebView;
}
webView初始化的時(shí)候給他一個(gè)高度就都顯示正常了。
第二個(gè)小坑:
當(dāng)前的操作邏輯是這樣的:
1、通過滑動(dòng)tableView,然后調(diào)用UITableViewDataSource的代理方法,
2、cell調(diào)用setModel方法進(jìn)行webView刷新,webView重新加載,
3、通過webView的代理方法<code>- (void)webViewDidFinishLoad:(UIWebView *)webView</code>獲取webView的高度
4、將這個(gè)高度回調(diào)或者通知給tableView,然后tableView刷新該cell的高度
滑動(dòng)cell的時(shí)候,更新cell的model,刷新界面
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell" forIndexPath:indexPath];
WebModel *model = self.dataSource[indexPath.row];
cell.model = model;
return cell;
}
webView獲取高度
#pragma mark- UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//獲取到webview的高度
CGFloat webViewHeight1 = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
CGFloat webViewHeight2 = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];
CGFloat webViewHeight3 = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.clientHeight"] floatValue];
NSLog(@"webViewHeight1 == %f",webViewHeight1);
NSLog(@"webViewHeight2 == %f",webViewHeight2);
NSLog(@"webViewHeight3 == %f",webViewHeight3);
webView.frame = CGRectMake(webView.frame.origin.x,webView.frame.origin.y, kScreenWidth, webViewHeight1);
// 獲取完畢之后以通知的形式,或者回調(diào)的形式通知tableView刷新
if (self.model.webViewHeight != webViewHeight1) {
self.model.webViewHeight = webViewHeight1;
[[NSNotificationCenter defaultCenter] postNotificationName:@"RefreshCell" object:nil];
}
}
VC中獲取刷新的通知,此時(shí)model的高度已經(jīng)修改,也就是說cell的高度已經(jīng)通過webView獲取到了
// 獲取通知
- (void)manageNoti
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshCell:) name:@"RefreshCell" object:nil];
}
// 通知方法,刷新tableView
- (void)refreshCell:(NSNotification *)notifaication
{
[self.myTableView reloadData];
}
第二個(gè)小坑悄無聲息的也來了。
如果這里webView獲取到高度就直接回調(diào)回去讓tableView去刷新,然后tableView又去刷新cell的model然后webView又會(huì)去獲取高度,獲取高度之后又去通知tableView去刷新,這樣下去就是一個(gè)死循環(huán)了。。。。。。。
最后獻(xiàn)上Demo地址:
https://github.com/RunOfTheSnail/TableViewInsertWebView