AutoLayoutを使ったビューをUITableViewCellのcontentViewにサブビュー追加したら Unable to simultaneously satisfy constraints. とかログが出た時の対処事例

More than 5 years have passed since last update.

AutoLayoutの細かいネタです。以下、AutoLayoutを使っている前提です。

以下のようなことをしたらエラーログが出てしばらくハマりました。。


  • xibを使ってカスタムビュー (仮に MyCustomView というクラスにしたとします)をAutoLayoutで作成。単体ではAutoLayoutの制約矛盾は起きてないのを確認済み。

  • MyCustomView を UINib 経由でインスタンス化し、適当な UITableViewCell のサブクラス(MyCustomCellとします)の contentView にサブビューとしてコードで追加する。

実行してみると以下のようなエラーログが出力されまして:

2014-05-21 21:35:24.392 test[86395:60b] Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x11ac7cdd0 V:[UILabel:0x11ac7cc90(17)]>",
"<NSLayoutConstraint:0x11ac7dcb0 V:[UIImageView:0x11ac7dbb0(1)]>",
"<NSLayoutConstraint:0x11ac7df80 V:[UIImageView:0x11ac7de80(1)]>",
// ... 中略 ...
"<NSLayoutConstraint:0x11ac7f850 UIImageView:0x11ac7d4b0.bottom == UIImageView:0x11ac7c140.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0x11a665760 h=-&- v=-&- MyCustomView:0x11ac7b490.height == UITableViewCellContentView:0x11ac7a010.height - 8>",
"<NSAutoresizingMaskLayoutConstraint:0x11a6675a0 h=--& v=--& V:[UITableViewCellContentView:0x11ac7a010(44)]>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x11ac7cdd0 V:[UILabel:0x11ac7cc90(17)]>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

AutoLayoutは賢く出来ているので、ぜんぶの制約を満たせない場合は適当に幾つか条件を諦めて続行してくれるので、アプリの実行自体はできるのですが、きもちわるいのでできれば警告が出ないように直したいところ。

いろいろ調べた末、 ios - Auto layout constraints issue on iOS7 in UITableViewCell - Stack Overflow という記事に行き当たり、これで解決できました。


  • translatesAutoresizingMaskIntoConstraints プロパティの効果により、 autoresizingMask がAutoLayoutと併用される場合に autoresizingMask は適当なNSLayoutConstraintに自動変換されて制約によるレイアウトが実現されるが、今回のサブビューの追加先である UITableViewCell の contentView に autoresizingMask が設定されていないために、制約不足でレイアウトが決まらずエラーになっていた

ということだったらしく、以下のように調整したらエラーログが出なくなり無事解決。


MyCustomCell.m


@implementation MyCustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {

UIViewAutoresizing autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

// MARK: ↓これが足りなかった
self.contentView.autoresizingMask = autoresizingMask;
// MARK: ↑これが足りなかった

UINib *nib = [UINib nibWithNibName:@"MyCustomView" bundle:nil];
MyCustomView *view = [[nib instantiateWithOwner:nil options:nil] firstObject];

view.autoresizingMask = autoresizingMask;
view.frame = self.contentView.bounds;
[self.contentView addSubview:view];
}
return self;
}


制約の組み方によっていろいろ訳の分からないエラーに悩むことも多いAutoLayoutなので、誰かの役に立つかもしれないので投稿してみました。