意外的NSAutoresizingMaskLayoutConstraint的AutoLayout约束问题

时间:2014-01-13 18:54:46

标签: ios objective-c uitableview autolayout

我正在以编程方式使用自动布局约束,并且我经常在我的应用程序中看到同样的错误,通常与看起来像这样的约束相关:

"<NSAutoresizingMaskLayoutConstraint:0x82da910 h=--& v=--& V:[UITableViewCellContentView:0x82d9fb0(99)]>"

我已经在https://github.com/nicolasccit/AutoLayoutCellWarning

添加了一些示例代码来重现

在这个例子中,我创建了一个包含2个UI元素的非常简单的视图:一个名为imageThumbnail的图像视图和一个名为labelName的标签,带有一些约束:

"H:|-padding-[_imageThumbnail(==imageWidth)]-[_labelName]";
"V:|-padding-[_imageThumbnail(==imageHeight)]-padding-|";
"V:|-padding-[_labelName]";

在两个元素上,我将AutoresizingMaskIntoConstraints设置为NO。

我得到以下例外:

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:0xa6e4f90 V:[UIImageView:0xa6e4340]-(10)-|   (Names: '|':UITableViewCellContentView:0xa6e4150 )>",
    "<NSLayoutConstraint:0xa6e4f10 V:[UIImageView:0xa6e4340(80)]>",
    "<NSLayoutConstraint:0xa6e4ed0 V:|-(10)-[UIImageView:0xa6e4340]   (Names: '|':UITableViewCellContentView:0xa6e4150 )>",
    "<NSAutoresizingMaskLayoutConstraint:0xa6e4ac0 h=--& v=--& V:[UITableViewCellContentView:0xa6e4150(99)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xa6e4f90 V:[UIImageView:0xa6e4340]-(10)-|   (Names: '|':UITableViewCellContentView:0xa6e4150 )>

我知道最后一个约束与内容视图有关,但我不清楚是否正确删除它(设置
在contentView上将AutoresizingMaskIntoConstraints设置为NO会引发错误,并且在下面的SO链接中,它会弄乱整个布局):

<NSAutoresizingMaskLayoutConstraint:0xa6e4ac0 h=--& v=--& V:[UITableViewCellContentView:0xa6e4150(99)]>

我在Auto layout constraints issue on iOS7 in UITableViewCell看到了答案,但这些答案似乎都不适合我。

我相信我定义的约束是有效且非常简单但似乎无法弄清楚发生了什么。我看到iOS 6.1和iOS 7都引发了异常。

知道我在这里做错了吗?

谢谢, 尼古拉斯

2 个答案:

答案 0 :(得分:8)

您应该更彻底地阅读例外说明:

Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints

简而言之,您看到的这种约束是由于某些UIView将其translatesAutoresizingMaskIntoConstraints设置为YES。在这种情况下,我怀疑这是单元格的内容视图,正如UITableViewCellContentView暗示的那样。

您只需将属性设置为NO即可将其停用。

cell.contentView.translatesAutoresizingMaskIntoConstraints = NO

编辑: 现在,请记住,这是一个临时修复,很可能您的约束有一些其他逻辑错误,例如将单元格contentView中的某些内容约束到单元格本身。或者通过看似强迫contentView大于单元格(因此大于其'自动调整大小)。

例如,你的细胞足够高吗?即它足够高,contentView高100?请注意,contentView必须高,可能不一定与单元格的高度匹配。

答案 1 :(得分:5)

我已将更正的代码版本放在https://github.com/mattneub/AutoLayoutCellWarning。完美的工作。这条线是你遇到麻烦的主要原因:

NSString *const kImageVertical = @"V:|-padding-[_imageThumbnail(==imageHeight)]-padding-|";

将其更改为

NSString *const kImageVertical = @"V:|-padding-[_imageThumbnail]-padding-|";

一切都会好的。

您遇到麻烦的主要原因是,通过为图像视图指定绝对高度,您无法为单元格指定高度。浮点不精确,因此您需要为单元格增加/缩小留出一些空间。如果我们取走绝对高度,图像视图将从其内在内容大小获得高度,优先级较低,因此没有冲突。

我对你的代码有一些其他批评。在使用自动布局时尝试动态设置单元格的高度时,您提供了您永远不应该给出的布局和约束更新命令,并且您在错误的时间给出它们。可以根据约束来执行动态行高,但是您执行此操作的方式并非如此。您所要做的就是致电systemLayoutSizeFittingSize以找出正确的细胞高度。此外,绝对不需要将“隐藏”单元格放入界面中。不要那样做;它只会混淆事物。当你查看我的代码版本时,你会注意到的一件事是它比你的更简单 ,因为存在这些差异。

有关工作方法,请参阅https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch08p424variableHeights/ch21p722variableHeights/RootViewController.m

上的示例

请参阅此问题的讨论in my book

编辑(2014年5月):不幸的是,我上面的回答未能指出此问题的一个主要原因,即单元格分隔符具有高度(如果它尚未设置为无)。因此,如果为单元格指定不考虑分隔符高度的高度,则无法将自动布局约束(如果为绝对)解析为该高度。 (参见this answer,这真的让灯泡在我脑海里浮现。)