添加顶部和底部约束会导致 UILabel 被压扁

Adding top and bottom constraints causes UILable to be squished

我以编程方式创建了一个自定义 UITableViewCell 并尝试在其中垂直居中放置两个 UILabel。但是 UILabel 最终被压扁了。在 Interface Builder 中使用原型单元执行相同的操作效果很好。我的代码有什么问题?

自定义视图单元格class

import UIKit

class TopViewCell: UITableViewCell {
    let df: DateFormatter = {
        let df = DateFormatter()
        df.dateFormat = NSLocalizedString("DATE_WEEKDAY", comment: "show date and weekday")
        return df
    }()
    var dateLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    var costLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let margin = contentView.layoutMarginsGuide
        
        contentView.addSubview(dateLabel)
        dateLabel.leadingAnchor.constraint(equalTo: margin.leadingAnchor).isActive = true
        dateLabel.topAnchor.constraint(equalTo: margin.topAnchor).isActive = true
        dateLabel.bottomAnchor.constraint(equalTo: margin.bottomAnchor).isActive = true
        
        contentView.addSubview(costLabel)
        costLabel.trailingAnchor.constraint(equalTo: margin.trailingAnchor).isActive = true
        costLabel.topAnchor.constraint(equalTo: dateLabel.topAnchor).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        dateLabel.text = df.string(from: Date())
        costLabel.text = "total: five thousand"
    }
}


自定义 UITableViewController class

import UIKit

class ItemViewController: UITableViewController {
    var itemStore: ItemStore!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(TopViewCell.self, forCellReuseIdentifier: "top_cell")
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return itemStore.allItems.count + 1
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell: UITableViewCell!
        
        if indexPath.row == 0 {
            cell = tableView.dequeueReusableCell(withIdentifier: "top_cell", for: indexPath)
        } else {
            cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = itemStore.allItems[indexPath.row - 1].name
            cell.textLabel?.font = cell.textLabel!.font.withSize(30)
            cell.detailTextLabel?.text = "$\(itemStore.allItems[indexPath.row - 1].valueInDolloar)"
        }
        
        return cell
    }
}

您的 TopViewCell 无法正确自动调整大小,因为您正在 layoutSubviews() 中设置文本。将这两行移动到 init,它的大小将正确:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    let margin = contentView.layoutMarginsGuide
    
    contentView.addSubview(dateLabel)
    dateLabel.leadingAnchor.constraint(equalTo: margin.leadingAnchor).isActive = true
    dateLabel.topAnchor.constraint(equalTo: margin.topAnchor).isActive = true
    dateLabel.bottomAnchor.constraint(equalTo: margin.bottomAnchor).isActive = true
    
    contentView.addSubview(costLabel)
    costLabel.trailingAnchor.constraint(equalTo: margin.trailingAnchor).isActive = true
    costLabel.topAnchor.constraint(equalTo: dateLabel.topAnchor).isActive = true

    // set the text here
    dateLabel.text = df.string(from: Date())
    costLabel.text = "total: five thousand"
}

作为旁注,您应该在使用 TopViewCell 时指定 class:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "top_cell", for: indexPath) as! TopViewCell
        return cell
    }
        
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.textLabel?.text = itemStore.allItems[indexPath.row - 1].name
    cell.textLabel?.font = cell.textLabel!.font.withSize(30)
    cell.detailTextLabel?.text = "$\(itemStore.allItems[indexPath.row - 1].valueInDolloar)"

    return cell
}

作为另一个旁注...您可以在故事板中创建两个原型单元格。