ios8 cell constraints break when adding disclosure

2020-02-26 15:08发布

I have a problem with auto layout on IOS8, the simplest case I can recreate is a simple tableView. I setup a static cell and then simply add a label.

My aim is to have the label largely fill the space, so I have three constraints on the label...

  1. Centre it vertically within the superview (I think this is fine)
  2. Set the label trailing margin to 30 (relative to superview)
  3. Set the label leading margin to 30 (relative to superview)

It's all absolutely fine and works perfectly with no major problems or warning (it does warn about zero height, but I don't think that so much of an issue for this)

Now ... if I add a disclosure indicator it all falls apart. It still looks ok, but I get the following:

2014-10-30 15:51:46.358 ContraintIssue[25572:1586028] 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:0x7fd3f3d23390 UITableViewCellContentView:0x7fd3f3d226f0.trailingMargin == UILabel:0x7fd3f3d227e0'Label'.trailing + 30>",
    "<NSLayoutConstraint:0x7fd3f3d235f0 UILabel:0x7fd3f3d227e0'Label'.leading == UITableViewCellContentView:0x7fd3f3d226f0.leadingMargin + 30>",
    "<NSLayoutConstraint:0x7fd3f53b73b0 'fittingSizeHTarget' H:[UITableViewCellContentView:0x7fd3f3d226f0(38)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fd3f3d23390 UITableViewCellContentView:0x7fd3f3d226f0.trailingMargin == UILabel:0x7fd3f3d227e0'Label'.trailing + 30>

I don't understand why adding an indicator would cause such a problem, it's nothing to do with the scale of the numbers, I've experimented quite a bit.

Any ideas?

The real world example a cell that has a label (the label) and then either another label or a text view that contains a value that can be set by following the disclosure. So the first label is a fixed size, the second ideally needs to be the max that it can be, but truncate the text if needed.

(See the 'ringtone' or 'vibration setting' within adding a contact for an example of what I'm trying to achieve)

Many thanks,

Lee.

3条回答
冷血范
2楼-- · 2020-02-26 15:20

I just had the same problem. I want to layout an image-view on the left hand with a label on its right which fills the space between the image-view and the right (or trailing) border of superview (which is the cell's content-view). Accessory view is set to disclosure indicator as well. As in your case the conflicting constraints where all H-based and one I found in the logs where fittingSizeHTarget. I didn't found out what this means nor where this was coming from, but I found your post here.

The following did the trick for me:

Lower the priority of your label's trailing-to-superview constraint. (I chose 990).

I assume, that the layout system (with the disclosure indicator visible) for what ever reason can't satisfy all the constraints anymore, so it breaks one. But if you lower the priority, it still tries to satisfy the constraint, but doesn't break it as the conflicting constraint(s) have higher priority.

Hope this solves your problem as well.

查看更多
一夜七次
3楼-- · 2020-02-26 15:24

Please pay attention to what Stephen says in the comment section of the upvoted answer. The upvoted answer is somewhat correct, but it's important to understand why it should only be used in certain scenarios.

Priorities are usually used in context where element A has a constraint saying height is equal or less/more than 300, and element B has one says height is equal or less/more than 500. Then autolayout can satisfy both conditions based on their priorities.

In this particular example, both constraints are set to specific value and lowering priority essentially tells to ignore that constraint if it's impossible to satisfy (there's no "partially ignore it"). However UILabel has an exception - default UILabel behaviour is to resize itself to fit the content unless it's constrained by additional margins (autosize constraint hides under fittingSizeHTarget name) and this behaviour sometimes shows false warnings. In reality this constraint will be ignored in the runtime, but before it becomes disabled internally it will file a warning. Therefore, even though we tell to ignore one of our constraints by lowering its priority (the one we set priority to 900), since autosize constraint will be ignored in runtime, our 900 priority will be applied and satisfied.

查看更多
▲ chillily
4楼-- · 2020-02-26 15:36

Raimunda's answer above explaining about the intrinsic size that happens on labels, buttons, etc being where this fittingSizeHTarget log is coming from was spot on. While you can leave it and let the system deal with it, it's a risky hack, because you're relying on the system to break an unwanted constraint...which it may not do in future releases. And in some cases, as in a view example I recently dealt with, lowering the priority of the trailing constraint to the outside safe area didn't prevent the label from overrunning (it did, however, fix the log warning lol).

For content issues like this, use the Content Hugging Priority and Content Compression Resistance Priority values. If you know that your label, for example, will want to increase in vertical height but constrain to a horizontal value, then make the vertical content hugging priority (Content hugging = the view resisting being made bigger) lower than the horizontal.

The Compression resistance is the opposite of this.

Then set your outside trailing constraint to a greater than or equal and you're good to go.

In the stack view below, the label titled Fake 4 actually overran and wanted to become two lines. That caused a conflict involving fittingSizeHTarget (the intrinsic content size wanted to stay on one line and overrun the view width). The key here was lowering the Horizontal Compression Resistance priority to lower than ALL of the other content priorities. This allowed me to lower the priority of the >= constraint on the trailing value, and everything behaves as expected.

Anyway, tweaking this stuff is annoying as heck, but those Hugging/Compression values, combined with some form of >= / <= are usually the answer.

Hope this helps.

enter image description here

查看更多
登录 后发表回答