UITableView 中的自动布局在启动应用程序时和应用程序启动后的结果不同 运行

Result with auto layout in a UITableView different when starting the app and once the app is running

我有一个在 Interface Builder 中创建的 UITableView。里面是动态细胞。我添加了这样的约束(此方法在 tableView:cellForRowAtIndexPath 中调用):

@IBOutlet weak var rowView: UIView!
@IBOutlet weak var flagImageView: UIImageView!
@IBOutlet weak var computedRateLabel: UILabel!
@IBOutlet weak var historyButton: UIButton!

func buildConstraintsFor() {
    let viewsDictionary = ["rowView": rowView, "flagImageView": flagImageView, "view1": computedRateLabel, "historyButton": historyButton]

    rowView.layer.borderWidth = 1
    flagImageView.layer.borderWidth = 1
    computedRateLabel.layer.borderWidth = 1
    historyButton.layer.borderWidth = 1

    rowView.layer.borderColor = UIColor.blackColor().CGColor
    flagImageView.layer.borderColor = UIColor.purpleColor().CGColor
    computedRateLabel.layer.borderColor = UIColor.orangeColor().CGColor
    historyButton.layer.borderColor = UIColor.greenColor().CGColor

    // remove constraints
    rowView.removeConstraints(rowView.constraints())
    historyButton.removeConstraints(historyButton.constraints())

    // add constraints
    rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[flagImageView]-[view1]-[historyButton]-|", options: nil, metrics: nil, views: viewsDictionary))
    rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[flagImageView]-1-|", options: nil, metrics: nil, views: viewsDictionary))
    rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[view1]-1-|", options: nil, metrics: nil, views: viewsDictionary))
    rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[historyButton]-1-|", options: nil, metrics: nil, views: viewsDictionary))

    // size
    historyButton.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[historyButton(==25)]", options: nil, metrics: nil, views: viewsDictionary))
    rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[rowView(<=68)]", options: nil, metrics: nil, views: viewsDictionary))
    rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[rowView(>=67)]", options: nil, metrics: nil, views: viewsDictionary))
    flagImageView.addConstraint(NSLayoutConstraint(item: flagImageView, attribute: .Width, relatedBy: .Equal, toItem: flagImageView, attribute: .Height, multiplier: 1, constant: 0))
}

当我 运行 应用程序时,我得到以下内容,这就是我想要的

当我滚动 TableView 并且当行消失并重新出现时(或者当我转到另一个 viewController 并返回时)我得到以下信息:

我不明白为什么。 如果我添加这个:

let width = UIScreen.mainScreen().applicationFrame.size.width
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[rowView(==\(width))]", options: nil, metrics: nil, views: viewsDictionary))

它似乎解决了问题,但当我横向时不再起作用。

是不是我做布局的时候做错了什么?

编辑:

当我在此处添加 rowView 的所有约束后打印它们的描述时,我得到的是:

<NSLayoutConstraint:0x17009f3b0 UIImageView:0x1701f5a00.leading == UITableViewCellContentView:0x1701968c0.leadingMargin>
<NSLayoutConstraint:0x17009f6d0 H:[UIImageView:0x1701f5a00]-(NSSpace(8))-[UILabel:0x13760f7f0'12 106,98']>
<NSLayoutConstraint:0x17009f9a0 H:[UILabel:0x13760f7f0'12 106,98']-(NSSpace(8))-[UIButton:0x137634b60]>
<NSLayoutConstraint:0x17009dec0 UITableViewCellContentView:0x1701968c0.trailingMargin == UIButton:0x137634b60.trailing>
<NSLayoutConstraint:0x170098920 V:|-(1)-[UIImageView:0x1701f5a00]   (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x17009a4a0 V:[UIImageView:0x1701f5a00]-(1)-|   (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x174098dd0 V:|-(1)-[UILabel:0x13760f7f0'12 106,98']   (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x174099550 V:[UILabel:0x13760f7f0'12 106,98']-(1)-|   (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x170283c00 V:|-(1)-[UIButton:0x137634b60]   (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x1702837a0 V:[UIButton:0x137634b60]-(1)-|   (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x170283d90 V:[UITableViewCellContentView:0x1701968c0(<=68)]>
<NSLayoutConstraint:0x170283de0 V:[UITableViewCellContentView:0x1701968c0(>=67)]>

我 post 我找到的解决方案,因为它可能有帮助。感谢拉姆的帮助。

确实,当您以编程方式使用自动布局时,请不要忘记在要添加约束的每个组件上添加 setTranslatesAutoresizingMaskIntoConstraints(false)

在我的例子中,我已经在 Interface Builder 中创建了约束,并且由于我需要在 运行 期间从我的行中删除一个 UILabel,我不得不为我的行重新创建约束(例如方面比例、宽度或高度)。因此,由于我只想更改我的组件在我的行中的位置,所以我不需要为 flagImageViewhistoryButton 重新创建约束,只要我不删除它们即可。

但是我需要从我的 rowView 中删除约束,因为我正在添加新约束并删除一些约束。这个rowView其实就是我UITableViewCellcontentView。通过删除约束,我也删除了链接到它的 superView 的约束,它实际上是 UITableViewCell 本身。所以我的 contentView 与其父项的大小不同。所以我只需要添加这两行:

rowView.superview?.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[rowView]-0-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.superview?.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[rowView]-0-|", options: nil, metrics: nil, views: viewsDictionary))