読者です 読者をやめる 読者になる 読者になる

UICollectionViewCell上のViewにAutoLayoutは設定できない?

UICollectionViewCell上のViewにAutoLayoutをしたら下記のようなwarningが出てAutoLayoutが効きません。環境はiOS8、Xcode6です。

SampleApp[3298:353432] 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:0x7baa3780 UIImageView:0x7baa3140.top == UIView:0x7baa2df0.top + 2>",
    "<NSLayoutConstraint:0x7baa37b0 UIView:0x7baa2df0.bottom == UIImageView:0x7baa3140.bottom + 4>",
    "<NSLayoutConstraint:0x7baa38a0 V:[UIImageView:0x7baa3140(64)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x7aea84f0 h=--& v=--& V:[UIView:0x7baa2df0(50)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7baa38a0 V:[UIImageView:0x7baa3140(64)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

layoutSubviewsでやる

やりたいのは、Cell上にアイコン的なUIImageViewとUILabelがのってるだけで、UILabelの幅を動的にサイズを変化させているCollectionViewCellの幅いっぱいに広げたい。Cell上のsubviewにAutoLayoutを設定したらStoryboard上ではwarning出てないけど、実行時にwarningが出て、効かないという状況です。設定違うのかな?うーん。

しょうがないので、UICollectionViewCellのカスタムクラスを作り、その中のlayoutSubviewsでやることにしました。

- (void)layoutSubviews
{
    [super layoutSubviews]; // 忘れずに

    CGFloat margin = 10;
    CGFloat maxBoundsX = CGRectGetMaxX(self.bounds) - margin;
    CGFloat labelWidth = maxBoundsX - CGRectGetMinX(self.label.frame);
    
    CGRect frame = self.label.frame;
    frame.size.width = labelWidth;
    [self.label setFrame:frame];
}

余談(AutoLayout)

重い腰をあげてやっとこさAutoLayoutに入門しているわけですが、使ってるうちに段々と分かってきた気がします。

  • viewとviewの間隔を順番にせっせと設定していけばなんとかなる
  • StoryBoard上でwarningとかErrorになっても恐れない
  • Costraintsの自動解決をせず自分を信じるw
  • 複雑な構成のviewは親viewにembed inして、そのviewの関係性を設定する

こうすればある程度人間でも理解できるレベルになってきます。