虽然您接下来的stackoverflow答案有很多上涨的选票,但似乎您采取了一个没有很好解释的要点(可能已经过时了),我认为这可能是导致您的问题的原因。
你会发现很多评论/文章/文章说你应该在
updateConstraints()
然而,
Apple's docs
也表示:
重写此方法以优化对约束的更改。
注释
在发生影响的更改之后,几乎总是更干净、更容易立即更新约束。例如,如果要更改一个约束以响应按钮点击,请直接在按钮的操作方法中进行更改。
只有当就地更改约束的速度太慢或视图产生大量冗余更改时,才应重写此方法。
我认为如果添加子视图,您将在尝试的内容中获得更好的结果。
和
当你的手机初始化时,它们的约束。
下面是一个简单的例子,它的布局与您所显示的类似。它创建了一个包含两个部分的表——第一个部分有一行,其中有一个“显示/隐藏”按钮。点击后,第二部分将添加/删除“驱动程序提示”行。
//
// InsertRemoveViewController.swift
//
// Created by Don Mag on 12/4/18.
//
import UIKit
struct MyRowData {
var title: String = ""
var value: CGFloat = 0.0
}
class OrderChargeTableViewCell: UITableViewCell {
static let boldCellIdentifier: String = "TTOrderDetailBoldTableViewCell"
static let regularCellIdentifier: String = "TTOrderDetailRegularTableViewCell"
var keyLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
var valueLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
contentView.addSubview(keyLabel)
contentView.addSubview(valueLabel)
let s = type(of: self).boldCellIdentifier
if self.reuseIdentifier == s {
NSLayoutConstraint.activate([
keyLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8.0),
keyLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8.0),
keyLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15.0),
valueLabel.centerYAnchor.constraint(equalTo: keyLabel.centerYAnchor, constant: 0.0),
valueLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15.0),
])
keyLabel.font = UIFont.systemFont(ofSize: 15, weight: .bold)
valueLabel.font = UIFont.systemFont(ofSize: 15, weight: .bold)
} else {
NSLayoutConstraint.activate([
keyLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 6.0),
keyLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4.0),
keyLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15.0),
valueLabel.centerYAnchor.constraint(equalTo: keyLabel.centerYAnchor, constant: 0.0),
valueLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15.0),
])
keyLabel.font = UIFont.systemFont(ofSize: 12, weight: .bold)
valueLabel.font = UIFont.systemFont(ofSize: 12, weight: .regular)
}
}
}
class TipCell: UITableViewCell {
var callBack: (() -> ())?
var theButton: UIButton = {
let b = UIButton()
b.translatesAutoresizingMaskIntoConstraints = false
b.setTitle("Tap to Show/Hide Add Tip row", for: .normal)
b.setTitleColor(.blue, for: .normal)
b.backgroundColor = .yellow
return b
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
contentView.addSubview(theButton)
NSLayoutConstraint.activate([
theButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20.0),
theButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20.0),
theButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor, constant: 0.0),
])
theButton.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
}
@objc func btnTapped(_ sender: Any?) -> Void {
callBack?()
}
}
class InsertRemoveViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var myData = [
MyRowData(title: "SUBTOTAL", value: 4),
MyRowData(title: "DELIVERY CHARGE", value: 1.99),
MyRowData(title: "DISCOUNT", value: -1.99),
MyRowData(title: "TOTAL", value: 4),
]
var tableView: UITableView = {
let v = UITableView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
func tipRowShowHide() {
let iPath = IndexPath(row: 3, section: 1)
if myData.count == 4 {
myData.insert(MyRowData(title: "DRIVER TIP", value: 2.0), at: 3)
tableView.insertRows(at: [iPath], with: .automatic)
} else {
myData.remove(at: 3)
tableView.deleteRows(at: [iPath], with: .automatic)
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(OrderChargeTableViewCell.self,
forCellReuseIdentifier: OrderChargeTableViewCell.regularCellIdentifier)
tableView.register(OrderChargeTableViewCell.self,
forCellReuseIdentifier: OrderChargeTableViewCell.boldCellIdentifier)
tableView.register(TipCell.self, forCellReuseIdentifier: "TipCell")
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 25
view.backgroundColor = .red
view.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 200.0),
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20.0),
tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20.0),
tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20.0),
])
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return " "
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? 1 : myData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "TipCell", for: indexPath) as! TipCell
cell.callBack = {
self.tipRowShowHide()
}
return cell
}
var cell: OrderChargeTableViewCell?
if indexPath.row == myData.count - 1 {
cell = tableView.dequeueReusableCell(withIdentifier: OrderChargeTableViewCell.boldCellIdentifier,
for: indexPath) as? OrderChargeTableViewCell
} else {
cell = tableView.dequeueReusableCell(withIdentifier: OrderChargeTableViewCell.regularCellIdentifier,
for: indexPath) as? OrderChargeTableViewCell
}
cell?.keyLabel.text = myData[indexPath.row].title
let val = myData[indexPath.row].value
cell?.valueLabel.text = String(format: "%0.02f USD", val)
return cell!
}
}
结果是: