TableView calculates wrong estimatedHeightForRowAt

You need to set tableFooterView to empty.

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.tableFooterView = UIView()
    // your staff
}

But still - as you can see in the video - the scroll indicator bar shows that wrong heights were calculated:

So what you want is precise content height.

For that purpose, you cannot use static estimatedRowHeight. You should implement more correct estimation like below.

    ...

    var sampleCell: WorldMessageCell?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UINib(nibName: "WorldMessageCell", bundle: nil), forCellReuseIdentifier: "WorldMessageCell")

        sampleCell = UINib(nibName: "WorldMessageCell", bundle: nil).instantiate(withOwner: WorldMessageCell.self, options: nil)[0] as? WorldMessageCell
    }

    ...

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        if let cell = sampleCell {
            let text = self.textForRowAt(indexPath)
            // note: this is because of "constrain to margins", which value is actually set after estimation. Do not use them to remove below
            let margin = UIEdgeInsets(top: 8, left: 20, bottom: 8, right: 20)
            // without "constrain to margins"
            // let margin = cell.contentView.layoutMargins 
            let maxSize = CGSize(width: tableView.frame.size.width - margin.left - margin.right,
                                 height: CGFloat.greatestFiniteMagnitude)
            let attributes: [NSAttributedString.Key: Any]? = [NSAttributedString.Key.font: cell.messageLabel.font]
            let size: CGRect = (text as NSString).boundingRect(with: maxSize,
                                                                 options: [.usesLineFragmentOrigin], attributes: attributes, context: nil)
            return size.height + margin.top + margin.bottom
        }
        return 100
    }

This is too precise (actually real row height) and maybe slow, but you can do more approximate estimation for optimization.