15

I'm trying to pin an UILabel to it's parent cell. I added four constraints (top, leading, trailing, bottom) which works fine on iOS 8.0 but not on iOS 7.X. Please see image below:

[Click here for full size]

enter image description here

What am I doing wrong? Please advise!

EDIT #1

It seems it's only broken since Xcode 6 GM. My approach was working fine in Xcode 6 beta 7.

Moreover, if I decrease the inner view's width, it throws the following warning:

2014-09-10 19:58:28.109 Test[57827: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:0x799573a0 H:|-(8)-[UIView:0x798a86e0]   (Names: '|':UIView:0x798ae5d0 )>",
    "<NSLayoutConstraint:0x799573d0 H:[UIView:0x798a86e0]-(43)-|   (Names: '|':UIView:0x798ae5d0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x798a8b00 h=--& v=--& H:[UIView:0x798ae5d0(50)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x799573d0 H:[UIView:0x798a86e0]-(43)-|   (Names: '|':UIView:0x798ae5d0 )>

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.
Attila H
  • 3,616
  • 2
  • 24
  • 37
  • Try setting the width and height of the UILabel equal to container. – puru020 Sep 10 '14 at 17:00
  • How do I do that? It's disabled (grayed out) – Attila H Sep 10 '14 at 17:02
  • Ctrl + Drag from the UILabel to the container and then select Equal Width and Equal Height. You have to this in 2 steps. – puru020 Sep 10 '14 at 17:05
  • I have no such option! Only these... http://i.imgur.com/NTVwcOC.png – Attila H Sep 10 '14 at 17:06
  • 2
    I am having the exact same issue. It used to work on Xcode 6 Beta 7 for iOS7 but now on XCode 6 GM on iOS7, the constraints are not being adhered to. – Uzair Khan Sep 10 '14 at 19:41
  • It looks like this has been solved here: https://stackoverflow.com/questions/25753373/ios-8-gm-does-not-update-constraints-on-collection-views/25768375#25768375 – Uzair Khan Sep 11 '14 at 14:19

6 Answers6

20

Overriding the custom cell's layoutSubviews is a possible workaround:

override func layoutSubviews() {
    contentView.frame = bounds
    super.layoutSubviews()
}
Attila H
  • 3,616
  • 2
  • 24
  • 37
  • 2
    Wow, that magically removed my ghost constraint: ``. Could you explain how this fixes that? Am I correct in assuming that it's because the contentView of cells come with a default margin (of 8px from the looks of it)? – pxlshpr Jan 12 '15 at 01:05
6

UIView:0x798ae5d0 is the contentView of the CollectionViewCell. Somehow at a certain moment it uses the UICollectionViewCells defaultSize, which is (50.0, 50.0).

<NSAutoresizingMaskLayoutConstraint:0x798a8b00 h=--& v=--& H:[UIView:0x798ae5d0(50)]>

As your horizontal margins 8 + 43 = 51 are bigger than the contentView (50) it is impossible to satisfy the layout.

<NSLayoutConstraint:0x799573a0 H:|-(8)-[UIView:0x798a86e0]   (Names: '|':UIView:0x798ae5d0 )>
<NSLayoutConstraint:0x799573d0 H:[UIView:0x798a86e0]-(43)-|  (Names: '|':UIView:0x798ae5d0 )>

One can make the layout more flexible, so that it also works on a (50.0, 50.0) size. In your case by changing equal 43 to <= 43 or by reducing a priority of 1000 to 750 or 999.

coco
  • 4,912
  • 2
  • 25
  • 33
  • This should be the accepted answer. In addition to being more concise, it uses auto layout priorities as they were intended. For example adding priorities like this `H:|-8@750-[view]-43@750-|`, should get rid of the warning. The answer which involves overriding `layoutSubviews` sets the frame of the `contentView` which should be avoided when using auto layout. – sabajt Dec 08 '15 at 22:55
5

The problem is that your custom view (UILabel) has constraints, which conflict with cell's (or better cell's contentView's) constraints. The cell's NSAutoresizingMaskLayoutConstraint are created automatically from what you set in UICollectionView properties in xib (or storyboard) as Cell Size. I have solved my similar problem (*) by explicitly setting

- (void)awakeFromNib {

    [super awakeFromNib];

    self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
}

in my custom UICollectionViewCell subclass. This gets rid of cell size constraint set in Storyboard.

(*) Disclaimer: My collectionView has self sizing cells based on their content view, which is defined by autolayout. I had warnings about conflicting constraints of my content autolayout, and explicit size in Storyboard. This helped me to get rid of those warnings.

Vilém Kurz
  • 3,401
  • 2
  • 34
  • 43
1

Instead of giving four constraints (top, leading, trailing, bottom). Try top, leading, width and height. It should work.

GameBegins
  • 580
  • 7
  • 12
0

I hope you have added constraints to the collection with respect to it's parent (which would be the view of the UIViewController) so that it's width and height is equal to the parent view.

enter image description here

puru020
  • 808
  • 7
  • 20
0

Just one more possibility that I found in my project.

Usually I copy/paste similar objects, but doing that, sometimes, holds the same ID.
So I fixed my constraint problem by creating an object from scratch.

Pedro Antunes
  • 192
  • 1
  • 6