Để UILabel tự điều chỉnh chiều cao theo nội dung (dynamic height), dùng Auto Layout + numberOfLines = 0 + constraints đúng. Không cần tính toán frame thủ công.
Cách hiện đại: Auto Layout (Khuyến khích)
- Set
numberOfLines = 0(unlimited lines). - Set constraints: Top, Leading, Trailing (và Bottom nếu là view cuối).
- Label tự co giãn chiều cao theo nội dung.
let label = UILabel()
label.numberOfLines = 0
label.text = "Dòng 1\nDòng 2\nDòng 3 rất dài sẽ tự động xuống dòng nếu không đủ chiều rộng..."
label.font = .systemFont(ofSize: 16)
label.textColor = .label
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
// Không cần height constraint - tự tính từ content
])
Cách cũ: Tính frame thủ công (Không khuyến khích)
// Chỉ dùng khi KHÔNG dùng Auto Layout (legacy code)
let label = UILabel()
label.frame = CGRect(x: 10, y: 40, width: 200, height: 50) // Cố định width
label.numberOfLines = 0
label.text = "Nội dung dài..."
label.sizeToFit() // Tự điều chỉnh height vừa khớp content (giữ width nguyên)
view.addSubview(label)

Extension tiện lợi
extension UILabel {
func setDynamicHeight(text: String, font: UIFont, maxWidth: CGFloat) -> CGFloat {
self.font = font
self.numberOfLines = 0
self.text = text
let size = self.sizeThatFits(CGSize(width: maxWidth, height: .greatestFiniteMagnitude))
return size.height
}
}
// Sử dụng:
let height = label.setDynamicHeight(text: "Nội dung...", font: .systemFont(ofSize: 16), maxWidth: view.frame.width - 32)
Kết quả dynamic

Lưu ý
- Auto Layout là chuẩn – không bao giờ set frame cứng cho dynamic content trong project hiện đại.
sizeToFit()chỉ hoạt động khi width cố định, không dùng với Auto Layout.preferredMaxLayoutWidth(tự động set khi dùng Auto Layout) kiểm soát width tối đa để wrap text.- Attributed Text: Cũng hoạt động tương tự với
numberOfLines = 0.