uitableview 内容大小未正确返回 swift
uitableview content size is not returning correctly swift
我在容器视图中使用 uitableview,所以想根据内容大小高度设置我的容器高度。
因此,在重新加载 tableview 之后,我正在更改 container.but 的高度,它似乎是根据估计的高度计算的。它没有给出实际高度。
这是我的约束布局。
谢谢..
instructiontableview.estimatedRowHeight = 55
instructiontableview.rowHeight = UITableViewAutomaticDimension
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// assigning multiline text to my label
cell.layoutIfNeeded()
cell.sizeToFit()
return cell
}
return UITableViewCell()
}
现在我正在从容器视图控制器重新加载并更改高度
您的大部分方法都是正确的,请在下面的步骤中添加此方法。如果您已经完成任何步骤,请打勾。
- 将标签
numberOfLines
属性 更改为零
- 为标签添加约束条件
- 更改高度约束关系
实现这两个tableView委托方法
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat{
return 55
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return UITableViewAutomaticDimension
}
现在 运行 您的项目并检查。
预期输出:
我尝试了 reloadData()
和 layoutIfNeeded()
并尝试了很多不同的方法。没有什么对我有用。最后我使用 KVO
解决了它。
这是我的代码
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.instructiontableview.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
}
override func viewWillDisappear(_ animated: Bool) {
self.instructiontableview.removeObserver(self, forKeyPath: "contentSize")
super.viewWillDisappear(true)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?){
if(keyPath == "contentSize"){
if let newvalue = change?[.newKey]{
let newsize = newvalue as! CGSize
self.heightofinstructioncontainerview.constant = newsize.height
}
}
}
如果您正在使用 iOS 13 和/或 Combine(就像我一样),那么您可以使用来自 tableview 的 KVO 属性的发布者
tableView.publisher(for: \.contentSize)
.receive(on: RunLoop.main)
.sink { size in
self.myViewsHeightConstraint.constant = size.height
self.tableView.isScrollEnabled = size.height > self.tableView.frame.height
}
.store(in: &cancellables)
这对我来说非常好,并且在每个布局过程中发布新值,如果您在 sink
闭包中放置断点,您可以在设备上实时看到这些值。
虽然这里提供的答案是正确的,但这里有另一个来自 Apple Developer Forum 的解释,其中指出 contentSize 最初与 estimated
值一样。所以把它设为零对我有用。
tableView.estimatedRowHeight = 0
苹果开发者论坛的回答如下:
In iOS 11, table views use estimated heights by default. This means that the contentSize is just as estimated value initially. If you need to use the contentSize, you’ll want to disable estimated heights by setting the 3 estimated height properties to zero: tableView.estimatedRowHeight = 0 tableView.estimatedSectionHeaderHeight = 0 tableView.estimatedSectionFooterHeight = 0
我在容器视图中使用 uitableview,所以想根据内容大小高度设置我的容器高度。 因此,在重新加载 tableview 之后,我正在更改 container.but 的高度,它似乎是根据估计的高度计算的。它没有给出实际高度。
这是我的约束布局。
谢谢..
instructiontableview.estimatedRowHeight = 55
instructiontableview.rowHeight = UITableViewAutomaticDimension
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// assigning multiline text to my label
cell.layoutIfNeeded()
cell.sizeToFit()
return cell
}
return UITableViewCell()
}
现在我正在从容器视图控制器重新加载并更改高度
您的大部分方法都是正确的,请在下面的步骤中添加此方法。如果您已经完成任何步骤,请打勾。
- 将标签
numberOfLines
属性 更改为零
- 为标签添加约束条件
- 更改高度约束关系
实现这两个tableView委托方法
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat{ return 55 } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{ return UITableViewAutomaticDimension }
现在 运行 您的项目并检查。
预期输出:
我尝试了 reloadData()
和 layoutIfNeeded()
并尝试了很多不同的方法。没有什么对我有用。最后我使用 KVO
解决了它。
这是我的代码
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.instructiontableview.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
}
override func viewWillDisappear(_ animated: Bool) {
self.instructiontableview.removeObserver(self, forKeyPath: "contentSize")
super.viewWillDisappear(true)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?){
if(keyPath == "contentSize"){
if let newvalue = change?[.newKey]{
let newsize = newvalue as! CGSize
self.heightofinstructioncontainerview.constant = newsize.height
}
}
}
如果您正在使用 iOS 13 和/或 Combine(就像我一样),那么您可以使用来自 tableview 的 KVO 属性的发布者
tableView.publisher(for: \.contentSize)
.receive(on: RunLoop.main)
.sink { size in
self.myViewsHeightConstraint.constant = size.height
self.tableView.isScrollEnabled = size.height > self.tableView.frame.height
}
.store(in: &cancellables)
这对我来说非常好,并且在每个布局过程中发布新值,如果您在 sink
闭包中放置断点,您可以在设备上实时看到这些值。
虽然这里提供的答案是正确的,但这里有另一个来自 Apple Developer Forum 的解释,其中指出 contentSize 最初与 estimated
值一样。所以把它设为零对我有用。
tableView.estimatedRowHeight = 0
苹果开发者论坛的回答如下:
In iOS 11, table views use estimated heights by default. This means that the contentSize is just as estimated value initially. If you need to use the contentSize, you’ll want to disable estimated heights by setting the 3 estimated height properties to zero: tableView.estimatedRowHeight = 0 tableView.estimatedSectionHeaderHeight = 0 tableView.estimatedSectionFooterHeight = 0