在我的 iOS 应用程序中,我想显示几个包含一些 HTML 的项目。为此,我构建了一个包含 UITableView 的 NewsListViewController。对于那个 UITableView(导出:newsListTableView),我创建了一个名为 NewsTableViewCell 的自定义 UITableViewCell,它将通过代表们。 NewsTableViewCell 包含一个将显示我的 HTML 的 WKWebKit 控件。这是我的代码:
NewsListViewController.swift
import UIKit
class NewsListViewController: UIViewController {
@IBOutlet weak var newsListTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.newsListTableView.delegate = self
self.newsListTableView.dataSource = self
self.newsListTableView.register(UINib(nibName: "NewsTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
}
}
extension NewsListViewController: UITableViewDelegate {
}
extension NewsListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 300.0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NewsTableViewCell
cell.titleText = "My Title"
cell.dateTimeText = "01.01.1998"
cell.contentHtml = "<html><head><meta name=\"viewport\" content=\"initial-scale=1.0\" /><style>html, body { margin: 0; padding: 0; font-size: 15px; }</style></head><body><b>Hello News</b><br />Hello News<br />Hello News<br />Hello News</body></html>"
return cell
}
}
NewsTableViewCell.xib
我的 WKWebKit(导出:newsContentPreviewWebView)位于 UIView(导出:newsContentViewContainer)内与 UIView 一起成长的适当约束。我的 UIView 也带有适当的约束,可以随着整个单元格的增长而增长。
NewsTableViewCell.swift
import UIKit
import WebKit
@IBDesignable class NewsTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var dateTimeLabel: UILabel!
@IBOutlet weak var newsContentViewContainer: UIView!
@IBOutlet weak var newsContentPreviewWebView: WKWebView!
@IBInspectable var titleText: String? {
get {
return self.titleLabel.text
}
set(value) {
self.titleLabel.text = value
}
}
@IBInspectable var dateTimeText: String? {
get {
return self.dateTimeLabel.text
}
set(value) {
self.dateTimeLabel.text = value
}
}
@IBInspectable var contentHtml: String? {
get {
return nil
}
set(value) {
self.newsContentPreviewWebView.loadHTMLString(value ?? "", baseURL: nil)
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.newsContentPreviewWebView.navigationDelegate = self
}
}
extension NewsTableViewCell: WKNavigationDelegate {
}
这是结果:
现在,我希望单元格尽可能小,但仍显示完整的 WKWebKit 内容。
当我删除...
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 300.0
}
...从 NewsListViewController.swift 单元格高度将只考虑 WKWebKit 控件上方的标签:
我认为这是发生了,因为当应用调整单元格大小时我的 WKWebKit 的内容没有加载。
我试图通过听取 WKWebKit 的 >> 完成导航 << 在我的 NewsTableViewCell.swift 中调用委托(delegate)并调整父 View 的大小来解决这个问题,像这样的整个单元格高度:
extension NewsTableViewCell: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
if complete != nil {
webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height, error) in
let h: CGFloat = height as! CGFloat
let newsContentFrame: CGRect = self.newsContentViewContainer.frame
self.newsContentViewContainer.frame = CGRect(x: newsContentFrame.minX, y: newsContentFrame.minY, width: newsContentFrame.width, height: h)
let tableCellFrame: CGRect = self.frame
self.frame = CGRect(x: tableCellFrame.minX, y: tableCellFrame.minY, width: tableCellFrame.width, height: tableCellFrame.height + h)
})
}
})
}
}
这是结果:
单元格重叠,这表明我试图以错误的方式解决这个问题。
自动调整自定义表格单元格大小以适应其所有内容(包括 WKWebKit 的内容)的正确方法是什么?
最佳答案
问题是你永远不会给你的单元格一个高度。手动设置框架
self.frame = CGRect(x: tableCellFrame.minX, y: tableCellFrame.minY, width: tableCellFrame.width, height: tableCellFrame.height + h)
不好。您应该始终使用专用委托(delegate)方法或估计行高技术 ( Using Auto Layout in UITableView for dynamic cell layouts & variable row heights )。
问题很棘手:您需要等待 webview 加载才能计算其高度。但是在加载 webview 的内容之前调用 heightForCell
时需要它的高度。
我看到 5 种解决方案:
- 您将 tableview 转换为包含所有新闻的巨大 webview。然后您将元数据手动注入(inject)到 html 中
- 您解析 html 并提取所需的信息。这只有在所有新闻 html 具有相同结构时才有可能。这也很难 ( RegEx match open tags except XHTML self-contained tags )。
- 你照原样进行。但是当
completionHandler
被调用时,您调用一个委托(delegate)(例如您的 View Controller ),它将重新加载相应的单元格并为其提供刚刚计算的正确高度。这个解决方案很简单,但在每次加载之前,你需要在你的单元格中给出一个错误的高度。因此,您可以在单元格中定义一个加载状态,但是当单元格即将出现时,您总会遇到一些小故障。 - 在显示表格 View 之前,加载所有单元格的内容并在后台线程上计算它们相应的高度。您可以为每个单元格使用
Operation
,等待单元格的 html 加载和评估给定的 javascript。完成所有操作后,重新加载 tableview - 更改您的设计:仅显示新闻列表并在选择单元格时将新闻内容加载到单独的 View Controller 中
关于ios - 如何使用底层 WKWebKit 自动调整 UITableViewCell 的大小,使其尊重 Web View 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48463531/