I have a simple UICollectionVewController with one prototype cell. In the cell all I have is a UILabel.
I have size classes and auto layout selected. I have set a constraint for
top (Top Space to cell): = 100
Height >= 17
Trailing space to Cell = 0
Leading Space to Cell = 0
In this configuration it works fine. However I want a left and right margin on the cell, so I changed the Leading and Trailing space to 10.
Although this works, I get the following error:
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:0x1740907c0 H:[UILabel:0x14de1a380'This is a test to see wha...']-(10)-| (Names: '|':UIView:0x14de1a270 )>",
"<NSLayoutConstraint:0x174090810 H:|-(10)-[UILabel:0x14de1a380'This is a test to see wha...'] (Names: '|':UIView:0x14de1a270 )>",
"<NSAutoresizingMaskLayoutConstraint:0x174090d10 h=--& v=--& H:[UIView:0x14de1a270(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x1740907c0 H:[UILabel:0x14de1a380'This is a test to see wha...']-(10)-| (Names: '|':UIView:0x14de1a270 )>
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.
If I set the leading space to 10 and remove the training space and set a width constraint, I do not get the error.
However, the width of the cell is variable so I can't set the width.
I can work around it, by creating an outlet to the width constraint and doing this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
CGRect colViewSize = collectionView.bounds;
int width = colViewSize.size.width;
width -= 28; // 10px either size and 8px in middle
width = width/2;
width -=14; // margin of 7 (x 2)
cell.labelconstraintWidth.constant = width;
return cell;
however this seems such a hack.
Does anyone have any clue what is happening here.
Simply put, your view resizes, and when it does, the constraints of 10 leading and 10 trailing space can't be satisfied because your view's width is less than 20.
Solution? Either put a percentual label margins / width to the superview or make the the margins zero, if you don't want to think about it.
However, if you have a encapsulated logic that calculates the cell width, you can easily add margin constraints from code.
EDIT:
You might have an autolayout constraint that's 50%, but that's not the issue here. You got an AutoResizingMaskLayoutConstraint that's affecting you view's width.
In order to create a percentual margin in storyboard, do:
1) Select your view in the view hierarchy
2) Hold CTRL and drag to your superview(or the root view that's taking the full bounds of the superview)
3) Select Horizontal Spacing
4) Select your view and double click on the Horizontal Spacing constraint
5) In the size inspector select:
First item: YourView.Leading
Relation: Equal
Second item: YourSuperview.Trailing
Constant: 0
Priority: 1000
Multiplier: (your margin percentage)
As #Bamsworld said, you should double check for AutoResizing masks. They might be conflicting with your AutoLayout constraints.
The error tells you one or more constraints is not needed and lists one of the constraints as NSAutoresizingMaskLayoutConstraint. It would appear that there is a conflict with auto-layout and autoresizingmasks. I suggest to use one or the other.
Try removing the autoresize-constraint by calling setTranslatesAutoresizingMaskIntoConstraints on the view and pass in NO. Also set the autoresizingMask property of the view to UIViewAutoresizingNone (just to be sure).
Related
Before iOS 8 (and it's SDK) I did auto height of UITableViewCell using this delegate method:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (!_prototypeCell)
{
_prototypeCell = [tableView dequeueReusableCellWithIdentifier:#"MyShowIdentifier"];
}
EventShow *show = self.myShows[indexPath.row];
self.prototypeCell.categoryNameLabel.text = show.event.category.name;
self.prototypeCell.eventNameLabel.text = show.event.title;
[self.prototypeCell layoutIfNeeded];
CGSize size = [self.prototypeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height + 1.0f;
}
My cell has two labels, one on top of the other with autolayout constraints telling the labels to grow vertically as much as the want. Everything worked fine.
After iOS 8 came, I get an "Unable to simultaneously satisfy constraints" error ONLY THE FIRST TIME THE METHOD systemLayoutSizeFittingSize: IS EXECUTED. The delegate method is called 3 times. This is the detail of the error:
(
"<NSLayoutConstraint:0x7fd1e8ebce30 H:|-(5)-[UILabel:0x7fd1eb0e00a0'Cine'] (Names: '|':UITableViewCellContentView:0x7fd1eb0c0210 )>",
"<NSLayoutConstraint:0x7fd1eb06b120 H:[UILabel:0x7fd1eb0e00a0'Cine']-(5)-| (Names: '|':UITableViewCellContentView:0x7fd1eb0c0210 )>",
"<NSLayoutConstraint:0x7fd1e8e7be50 'UIView-Encapsulated-Layout-Height' H:[UITableViewCellContentView:0x7fd1eb0c0210(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fd1eb06b120 H:[UILabel:0x7fd1eb0e00a0'Cine']-(5)-| (Names: '|':UITableViewCellContentView:0x7fd1eb0c0210 )>
There is a new constraint there called "UIView-Encapsulated-Layout-Height" with is set to zero. I don't now what that is, but I'm sure it should be > 0.
The auto height still works in iOS 8, but it throws this error that i can't fix.
Any ideas? Thanks a lot!
The error you are getting is for width of label as you had set specific width and you also set leading and trailing constraint. So what is happening here is to label is breaking leading,trailing or width constraint to satisfy trailing constraint of label.
But to satisfy your constraint for trailing it will break width constraint.
What you need to do here is just set leading,top, trailing and bottom constraint to both the label. Also you need to set vertical spacing between those label and no need to set height and width constraints to both label.
Also in attribute inspector you set lines = 0, Line Breaks = Word Wrap.
you also need to set “self.tableView.rowHeight = UITableViewAutomaticDimension;” in viewDidLoad.
when I run my app on an iPhone I get the following errors. When I run it in the simulator I do not. If I take the -12-| away then the cell's height collapses to something like 30 pixels. And the UI breaks.
Can someone help me and tell me why?
Thanks
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:0x170285ff0 V:|-(12)-[UIImageView:0x1741ec200] (Names: '|':UITableViewCellContentView:0x17419c7d0 )>",
"<NSLayoutConstraint:0x170286040 V:[UIImageView:0x1741ec200(200)]>",
"<NSLayoutConstraint:0x170286090 V:[UIImageView:0x1741ec200]-(12)-| (Names: '|':UITableViewCellContentView:0x17419c7d0 )>",
"<NSLayoutConstraint:0x174881f40 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x17419c7d0(224)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x170286090 V:[UIImageView:0x1741ec200]-(12)-| (Names: '|':UITableViewCellContentView:0x17419c7d0 )>
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.
Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead.
Unable to simultaneously satisfy constraints.
In a custom UITableViewCell I defined the Layout Constraints as follows:
_imgView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-15-[imageView]-15-|" options:0 metrics:nil views:#{ #"imageView": _imgView }]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-12-[imageView(200)]-12-|" options:0 metrics:metrics views:#{ #"imageView" : _imgView }]];
--- EDIT ---
In response to the contentView.bounds suggestion:
In my UITableViewController I implement the following:
_tableView.rowHeight = UITableViewAutomaticDimension;
_tableView.estimatedRowHeight = 30.0f;
So a zero height, should not be an issue.
The initial height of the cell is likely smaller than the vertical constraints. This creates an initial height conflict until the contentView's frame changes.
You can work around this issue using one of the following approaches:
Increase the cell's height in the storyboard to initially fit the content.
Change the bounds of the cell's contentView to a larger size:
self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);
You'll find more details in the answers to this auto layout question.
Update:
The "Unable to simultaneously satisfy constraints" conflict is between the imageView constraints trying to set the cell's height to 225 points, and the fixed height trying to set the cell height to 224 points.
Your imageView vertical constraints use 224 (12 + 200 + 12) points. The tableView separator uses 1 point. So the cell height needs to be 225 points for all constraints to be met.
I have cell with only one button in it, I've added height of button = 30, top = 10 and bottom = 10 constraints, so systemLayoutSizeFittingSize must return height of cell = 50. Nevertheless it returns 50.5 and I see in the log :
Will attempt to recover by breaking constraint
I'm using grouped table view and separator set to none. Where it takes extra 0.5px?
code snippet:
[cell layoutSubviews];
return [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;// 50;
log:
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:0x7ffa71e273e0 V:[UIButton:0x7ffa71e24900'Book a new hotel'(30)]>",
"<NSLayoutConstraint:0x7ffa71e20bc0 V:|-(10)-[UIButton:0x7ffa71e24900'Book a new hotel'] (Names: '|':UITableViewCellContentView:0x7ffa71e06030 )>",
"<NSLayoutConstraint:0x7ffa71e23ae0 UITableViewCellContentView:0x7ffa71e06030.bottomMargin == UIButton:0x7ffa71e24900'Book a new hotel'.bottom + 2>",
"<NSLayoutConstraint:0x7ffa705f6640 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7ffa71e06030(50.5)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7ffa71e273e0 V:[UIButton:0x7ffa71e24900'Book a new hotel'(30)]>
iOS 8
If your target is iOS8 then it makes this much easier as table view cells can now be sized automagically by AutoLayout.
To do this just return UITableViewAutomaticDimension in your heightForRow method...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
Essentially this does what I think you are trying to do with your code snippet.
iOS 7
For iOS 7 I'd set out the constraints differently. Instead of setting the top and bottom constraints I'd just have a "centre vertically" constraint.
Then you can return any number you want to return and the constraints won't break.
You don't get the automatic height thing but the height doesn't appear to change anyway.
I've got a UITableViewCell which contains a UIWebView. The table view cell adjusts it's height depending on the web view contents.
I've got it all working fine, however when the view loads, I get a constraint violation exception in the debugger (the app continues running and functionally works fine, but I'd like to resolve this exception if possible).
How I've got it set up:
The TableView sets the cell height like this:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.section == 0) {
[_topCell layoutIfNeeded];
CGFloat finalHeight = [_topCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return finalHeight + 1;
}
The cell constraints are as follows:
Arbitrary 7px offset from the cell's contentView (top) to the webView
Web view has arbitrary fixed height constraint of 62px (will expand later once content loads)
Arbitrary 8px offset from the webView to the cell's contentView (bottom)
in my viewDidLoad, I tell the webView to go and load a URL, and in the webViewDidFinishLoad, I update the web view height constraint, like this
-(void)webViewDidFinishLoad:(UIWebView *)webView {
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
// fittingSize is approx 500
[self.tableView beginUpdates];
// Exceptions happen on the following line setting the constant
_topCell.webViewHeightConstraint.constant = fittingSize.height;
[_topCell layoutSubviews];
[self.tableView endUpdates];
}
The exception looks like this:
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:0x10964b250 V:[webView(62)] (Names: webView:0x109664a00 )>",
"<NSLayoutConstraint:0x109243d30 V:|-(7)-[webView] (Names: webView:0x109664a00, cellContent:0x1092436f0, '|':cellContent:0x1092436f0 )>",
"<NSLayoutConstraint:0x109243f80 V:[webView]-(8)-| (Names: cellContent:0x1092436f0, webView:0x109664a00, '|':cellContent:0x1092436f0 )>",
"<NSAutoresizingMaskLayoutConstraint:0x10967c210 h=--& v=--& V:[cellContent(78)] (Names: cellContent:0x1092436f0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x10964b250 V:[webView(62)] (Names: webView:0x109664a00 )>
This seems a bit weird. It's implied that the constraint which sets the height of the web view is going to be broken, however the web view does get it's height correctly set, and the tableview renders perfectly well.
From my guesses, it looks like the newly increased web view height constraint (it's about 500px after the web view loads) is going to conflict with the <NSAutoresizingMaskLayoutConstraint:0x10967c210 h=--& v=--& V:[cellContent(78)] setting the cell height to 78 (put there by interface builder). This makes sense, however I don't want that cell content to have a fixed height of 78px, I want it to increase it's height, and functionally, it actually does this, just with these exceptions.
I've tried setting _topCell.contentView.translatesAutoresizingMaskIntoConstraints = NO; to attempt to remove the NSAutoresizingMaskLayoutConstraint - this stops the exceptions, but then all the other layout is screwed up and the web view is about 10px high in the middle of the table view for no reason.
I've also tried setting _topCell.contentView.autoresizingMask |= UIViewAutoresizingFlexibleHeight; in the viewDidLoad to hopefully affect the contentView 78px height constraint, but this has no effect
Any help would be much appreciated
An alternative answer, which ends up being far simpler:
Set the priority of the webViewHeight constraint to something other than required. Works well and there are no warnings. I'd recommend going with this :-)
I worked out a solution. It seems like a hack, but it works correctly and produces no errors and warnings.
The trick was to dissociate the web view's layout and height from the contentView.
I did this as follows:
In the tableviewcell, add a new UIView, called containerView
Give it constraints for Top:0 Left:0 Right:0 but no bottom constraint and no height constraint
Put the web view (and any other content) inside this containerView
Add constraints such that the web view is 7px from the top and bottom of containerView, and has a height constraint of 62px
At this point, the containerView isn't connected to the bottom of the table view cell, and so it could over/under flow without auto-layout complaining.
Now, in tableView:heightForRowAtIndexPath:, we calculate the cell height based on the containerView as follows:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.section == 0) {
CGFloat finalHeight = [_topCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return finalHeight + 1;
}
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
All done!
From the Constraint log
The Constraint you are trying to achieve is as below,
In a 78 px cellContentHeight you want to fit a content of 7(top space) + 62 (Web View) + 8 (bottom space). which is 77 (not equal to 78). Either of two option would work,
Try giving top margin as 8 (instead of 7) and make it 78. (V:|-8-[WebView(62)]-8-|)
Attach to the top, give 8 pixel top space (V:|-8-[WebView(62)]) and don't specify 8 px bottom space.
Attach to Bottom, give 8 pixel bottom space (V:[WebView(62)-8-|) and don't specify top space.
I'm using UIView+Autolayout, to make code-based Auto Layout constraint creation easier, but I'm having trouble adding a constraint to a UITableViewCell sub class.
I have a subview ("viewUser") in the cell to group contact information about who posted the other content being shown in the cell. "viewUser" is a fixed height and is always at the bottom of the cell:
To achieve this in the init method I create "viewUser" and add it to the cell's contentView:
self.viewUser = [UIView newAutoLayoutView];
[self.contentView addSubview:self.viewUser];
and in the updateConstraints method I add the following constraints:
[self.viewUser autoSetDimension:ALDimensionHeight toSize:kContentHeight];
[self.viewUser autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0.0f];
[self.viewUser autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:0.0f];
[self.viewUser autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:0.0f];
[self.viewUser autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:0.0f];
When I then create the cells, I get the following warning in the console:
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) (
<NSAutoresizingMaskLayoutConstraint:0xb2a6b40 h=--& v=--& V:[UITableViewCellContentView:0xb289e20(44)]>",
"<NSLayoutConstraint:0xb2a3360 V:[UIView:0xb2a5fd0(53)]>",
"<NSLayoutConstraint:0xb2a3420 V:|-(0)-[UIView:0xb2a5fd0] (Names: '|':UITableViewCellContentView:0xb289e20 )>",
"<NSLayoutConstraint:0xb2a3840 UIView:0xb2a5fd0.bottom == UITableViewCellContentView:0xb289e20.bottom>" )
Will attempt to recover by breaking constraint <NSLayoutConstraint:0xb2a3360 V:[UIView:0xb2a5fd0(53)]>
Which to me makes sense because I'm saying that "viewUser" should have a fixed height and then I pin it to the contentView's edges however if I remove:
[self.viewUser autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0.0f];
When I work out the cell's dynamic height in my tableview controller, its height comes back as 0.
I can't work out what I'm doing wrong and how I remove this warning and get the cell's height, any insights would be great.
It's difficult to diagnose you're problem without knowing the entire layout for your cell. Most likely, you're returning the incorrect height in
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
The height you're returning is too small for both "viewUser" and the content subview above.
If you're "viewUser" is disappearing, there are two scenarios I can think of right now that can result from your table cell height being too small.:
You're height constraint for viewUser was broken automatically at
runtime due to constraint conflicts. This is what happens in the
warning you posted: cell height was too small (44) for your viewUser
height (53)
You're viewUser's height is superseded by a higher priority
constraint possibly from the content view. This is less unlikely but is also a possibility.