- 一. 設(shè)置 estimatedRowHeight
一般來講計算cell
的高度需根據(jù)數(shù)據(jù)模型的內(nèi)容長度锌钮,決定單元格高度漏益,按照常規(guī)的方式鳍征,需要先給出單元格高度搁料,代理才會執(zhí)行cellForRow
函數(shù)狼讨,如果height
為0的話贝淤,cellForRow
函數(shù)就不執(zhí)行了,而我們的計算卻發(fā)生在cellForRow
函數(shù)中政供,計算完成后再刷新播聪,但是這樣不可行。
正確方式: 首先設(shè)置tableView
的預(yù)估高度布隔,這樣的話离陶,代理就會首先執(zhí)行cellForRow
函數(shù),這樣就可以先計算执泰,計算完成后保存起來枕磁,然后再執(zhí)行heightForRow
函數(shù),讀取剛才保存的值术吝。
tableView.estimatedRowHeight = 500
- 二. 設(shè)置
beginUpdates
以及endUpdates
函數(shù)
對于cell
中有按鈕或者其他出發(fā)事件時動態(tài)修改cell
高度的情況计济,可以在觸發(fā)事件中調(diào)用 beginUpdates
和 endUpdates
兩個函數(shù),該函數(shù)的作用區(qū)別于調(diào)用 reloadData
排苍,刷新時只會更新高度沦寂,而不會重新調(diào)用 cellForRow
函數(shù)。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.beginUpdates()
let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
allHeight[key] = 200
tableView.endUpdates()
}
example
- vc
import UIKit
class TestVC: UIViewController {
public var allHeight = [String: CGFloat]()
lazy var tableView: UITableView = {
let temp = UITableView()
temp.delegate = self
temp.dataSource = self
temp .register(TestTableViewCell.self, forCellReuseIdentifier: TestTableViewCell.description())
return temp
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.frame = view.bounds
view.addSubview(tableView)
tableView.estimatedRowHeight = 500;
tableView.reloadData()
}
}
extension TestVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
debugPrint("cellForRowAt")
guard let cell = tableView.dequeueReusableCell(withIdentifier: TestTableViewCell.description(), for: indexPath) as? TestTableViewCell else { return UITableViewCell() }
cell.content = "獲取 = \(indexPath.row)"
let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
if !allHeight.keys.contains(key) {
let value = cell.dynamicHeight
allHeight[key] = value
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
debugPrint("heightForRowAt")
let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
guard let height = allHeight[key] else { return 0 }
return height
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.beginUpdates()
let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
allHeight[key] = 200
tableView.endUpdates()
}
}
- cell
import UIKit
class TestTableViewCell: UITableViewCell {
public var content: String? {
didSet {
dynamicHeight = 100
self.textLabel?.text = content
}
}
private (set) public var dynamicHeight: CGFloat = 0
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}