class MultilineLabelCell: UITableViewCell { let label = UILabel() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } private func commonInit() { label.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(label) let g = contentView.layoutMarginsGuide NSLayoutConstraint.activate([ label.topAnchor.constraint(equalTo: g.topAnchor), label.leadingAnchor.constraint(equalTo: g.leadingAnchor), label.trailingAnchor.constraint(equalTo: g.trailingAnchor), label.bottomAnchor.constraint(equalTo: g.bottomAnchor), ]) label.numberOfLines = 0 // so we can see the framing label.backgroundColor = .yellow } } class ReloadRowsTestVC: UIViewController, UITableViewDelegate, UITableViewDataSource { var myData: [String] = [] var reloadCount: Int = 0 let tableView = UITableView() override func viewDidLoad() { super.viewDidLoad() // some sample data for i in 1..<50 { let nLines = i % 4 var s: String = "Row: \(i-1)\nLine 1" for n in 0.. Int { return myData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("cellForRowAt:", indexPath) let c = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath) as! MultilineLabelCell c.label.text = myData[indexPath.row] return c } }