内容简介:产品中频繁遇到UITableViewCell含有WebView的需求,也提出好几个解决方案了,当然一次比一次简单。去年我总结出这个方案如果相等,OK,第 i 个 cell 显示正确。
产品中频繁遇到UITableViewCell含有WebView的需求,也提出好几个解决方案了,当然一次比一次简单。
旧方案
去年我总结出这个方案 完美解决 UITableViewCell 中加载 UIWebView 的高度计算问题 ,我的思路是:
- 获取数据,确定 tableView 的 cell 的数目和初始高度。
- 刷新 tableView,向每一个 cell 填充内容和初始高度,将初始高度赋值给 cell 的一个变量 cellHeight,并加载 webView。
- 等第 i 个 cell 中的 webView 加载完毕之后计算其高度 h。
- 令 h 与 cellHeight 进行比较。如果两个高度不等,通知 tableView 第 i 个 cell 的高度 h (即 cell 中 webView的实际高度),并调用如下代码刷新 cell:
tableView.reloadRows(at: [IndexPath (row: i, section: 0)], with: .none) 复制代码
如果相等,OK,第 i 个 cell 显示正确。
- 重复 3。
新方案
最近在做一个新的产品,又遇到了这个需求。本来我的想法是从上一个项目直接copy代码过来,但是看了半天觉得太过繁琐,再加上最近看了一些UITableViewCell自适应高度的文章,就想换种写法。
一般情况下,实现UITableViewCell自适应高度这样做:
- 设置UITableView自适应cell高度
tableView.estimatedRowHeight = 76
tableView.rowHeight = UITableView.automaticDimension
复制代码
- UITableViewCell设置从top到bottom完整的约束
questionWebView.snp.makeConstraints { (make) in
make.edges.equalToSuperview().inset(UIEdgeInsets.init(top: 8, left: 16, bottom: 8, right: 16))
make.height.equalTo(60)
}
复制代码
对于一般的view,这两步之后就可以实现cell的自适应高度了。
但是对于webView,在开始加载时webView的高度并不固定,所以要在webView加载完毕后获取其高度并刷新cell。这一步就不用旧方案的step4来刷新cell了。
首先为webView监听webView加载:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.separatorStyle = .none
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! ExerciseQuestionCell
// 为cell设置数据
cell.setData(exerciseArray[indexPath.row])
// 监听webView加载
cell.questionWebView.delegate = self
cell.selectionStyle = .none
return cell
}
复制代码
获取webView的高度。
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// 当webview加载完成,计算并刷新高度
webView.evaluateJavaScript("document.body.scrollHeight") { (any, error) in
// height就是加载完毕的webView的高度
let height = any as! Int
}
}
复制代码
获取到高度后调整webView的高度:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// 当webview加载完成,计算并刷新高度
webView.evaluateJavaScript("document.body.scrollHeight") { (any, error) in
// height就是加载完毕的webView的高度
let height = any as! Int
// 调整webView高度
loadingWebView.snp.updateConstraints { (make) in
make.height.equalTo(height)
}
// 刷新tableView
exerciseTable.beginUpdates()
exerciseTable.endUpdates()
}
}
复制代码
到这里效果就出来了
但是在这里我发现当滑动table时模拟器会变得十分卡顿,调试发现ExerciseQuestionCell的setData(exercise)方法在一直被调用,setData方法如下:
func setData(_ exercise: Exercise) {
do {
let data = exercise.question.data(using: .utf8)
let questionObject = try JSON.init(data: data!)
let question = questionObject["question"].stringValue
let questionHtml = DIV_HEAD + question + DIV_FOOT
webView.loadHTMLString(htmlString, baseURL: nil)
} catch {
print(error)
}
}
复制代码
我想可能是刷新tableView的时候调用setData方法,setData里面调用webView.loadHTMLString方法加载html,加载完毕后又刷新tableView......产生循环,所以我在ExerciseQuestionCell里面设置了一个变量loadedData来记录cell是否设置过数据,如果设置过数据就不再设置了:
func setData(_ exercise: Exercise) {
if loadedData {
// 设置过数据之后就不再设置,防止多次刷新
return
}
do {
let data = exercise.question.data(using: .utf8)
let questionObject = try JSON.init(data: data!)
let question = questionObject["question"].stringValue
let questionHtml = DIV_HEAD + question + DIV_FOOT
questionWebView.loadHtmlString(questionHtml)
} catch {
print(error)
}
loadedData = true
}
复制代码
这样一来就很清爽了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- [译] React v16.8: 含有Hooks的版本
- VC++ 工程中含有同名源代码文件导致的坑
- 如何用Jackson解析含有转义字符的JSON到Java对象?
- linux查找目录下的所有文件中是否含有某个字符串
- Website Planet实测:5个热门网站代管平台皆含有安全漏洞
- 工作中的坑——dom4j解析含有命名空间的XML的坑
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
High Performance Python
Micha Gorelick、Ian Ozsvald / O'Reilly Media / 2014-9-10 / USD 39.99
If you're an experienced Python programmer, High Performance Python will guide you through the various routes of code optimization. You'll learn how to use smarter algorithms and leverage peripheral t......一起来看看 《High Performance Python》 这本书的介绍吧!