Posted at

UITableViewCellでAutoLayoutを使ったときに出る警告

More than 1 year has passed since last update.

UITableViewでAutoLayoutを使う時は、UITableViewAutomaticDimensionを使い高さ計算を自動でやると思います。

その時に一覧画面でよくあるようなこのようなCellを作ると

@3x端末のみ警告が出る場合があります。

class CustomCell: UITableViewCell {

let iv: UIImageView = {
let iv = UIImageView()
//初期化処理
return iv
}()

let label: UILabel = {
let label = UILabel()
//初期化処理
return label
}()

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)

contentView.addSubview(iv)
contentView.addSubview(label)
}

func setupConstraints() {
let margin = 10

iv.snp.makeConstraints { (make) in
make.top.left.bottom.equalToSuperview().inset(margin)
make.size.equalTo(50)
}
label.snp.makeConstraints { (make) in
make.top.right.equalToSuperview().inset(margin)
make.left.equalTo(iv.snp.right).offset(margin)
make.bottom.equalTo(iv)
}
}
}

[LayoutConstraints] Unable to simultaneously satisfy constraints.

Will attempt to recover by breaking constraint
<SnapKit.LayoutConstraint:0x6080000a8f40@ViewController.swift#79 UIImageView:0x7fdd23604d70.height == 50.0>

※snapkitを使っているためStoryBoardの時とは微妙に警告は違います。


原因

CellのlayoutSubviews()にてframeのサイズを見ればわかりますが、TableViewが罫線を追加するところで値がおかしなっているため制約を満たせなくなってるためです。

本来罫線は1pxなので0.3333333333にになるはずだけど、

小数点第6位からおかしくなってるのは内部的な数値の扱いは32bit?

// 1回目(制約通りにサイズが大きくなってるのでエラーなし)

self:(0.0, 0.0, 414.0, 70.3333333333333)
contentView:(0.0, 0.0, 414.0, 70.0)

// 2回目(微妙に小数点がずれているため制約を満たせなくなる)
self:(0.0, 0.0, 414.0, 70.3333358764648)
contentView:(0.0, 0.0, 414.0, 70.0000025431315)


対処法

微妙に数値がおかしくなるので、どこか一つのPriorityを下げておくだけです。

1:どこか一つのpriorityを下げる

iv.snp.remakeConstraints { (make) in
make.top.left.equalToSuperview().inset(margin)
make.bottom.equalToSuperview().inset(margin).priority(UILayoutPriorityDefaultHigh)
make.size.equalTo(50)
}

2:どこか一つをequalToSuperviewの代わりにlessThanOrEqualToSuperviewを使う
iv.snp.remakeConstraints { (make) in
make.top.left.equalToSuperview().inset(margin)
make.bottom.lessThanOrEqualToSuperview().inset(margin)
make.size.equalTo(50)
}