【问题标题】:AutoLayout constraint issue with unexpected NSAutoresizingMaskLayoutConstraint意外 NSAutoresizingMaskLayoutConstraint 的 AutoLayout 约束问题
【发布时间】:2014-01-13 18:54:45
【问题描述】:

我正在以编程方式使用自动布局约束,并且在我的应用程序中经常看到相同类型的错误,通常与如下所示的约束有关:

"<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 中都出现了异常。

知道我在这里做错了什么吗?

谢谢, 尼古拉斯

【问题讨论】:

    标签: ios objective-c uitableview autolayout


    【解决方案1】:

    您应该更彻底地阅读异常描述:

    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 有 100pt 高?请注意,contentView 必须那么高,这可能不一定与单元格的高度匹配。

    【讨论】:

    • 感谢您的回答,但我不认为这是正确的。我不相信您应该在 contentView 上设置 autoResizingMaskIntoConstraints。首先,在我链接到的 SO 问题中,解释为:“我无法将 contentView 的 translatesAutoresizingMaskIntoConstraints 属性设置为 NO => 它会弄乱整个单元格。”在我的情况下,如果我尝试,我会得到以下异常:“由于未捕获的异常‘NSInternalInconsistencyException’而终止应用程序”。除非我还缺少其他东西。
    • 这可能有助于解决后一个异常。 stackoverflow.com/questions/12610783/… 但是,是的,理想情况下您不需要操纵所述属性,在您的情况下,您的布局尺寸显然存在逻辑错误......例如,摆脱图像的高度限制并注销它的框架后布局已经完成,我怀疑它不会是 80pt(意味着根本没有足够的空间来实现你想要的布局)。
    • 如果我去掉图片的高度限制,异常消失,帧高变成23.0。虽然 UI 与我有约束时相同。当我让约束并打印图像的框架高度时,它是 80.0。
    • 感谢您的编辑。你的意思是“你的细胞够高吗?”。我没有硬编码单元格的高度。我放在 github 上的示例是一个愚蠢的示例,其中所有单元格恰好具有相同的高度,但我使用 heightForRowAtIndexPath 来计算每个单元格的高度。我错过了什么吗?
    • @HenriNormak 非常感谢
    【解决方案2】:

    我已将您的代码的更正版本放在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,这真的让我脑子里冒出了灯泡。)

    【讨论】:

    • 有趣。如果我尝试这个,我得到以下异常:“***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'执行-layoutSubviews后仍然需要自动布局。TableViewCell的-layoutSubviews实现需要调用super。'”您是否在以下行之后添加了它:“if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {”?
    • 嗨,马特,我一直在尝试按照这个来设置我的约束和布局命令:stackoverflow.com/questions/18746929/… 对于简单的情况,我在 github 上,我真的不需要灵活的单元格高度,但在我的真实案例中,我使用多行标签。你介意澄清我做错了什么吗?基本上,为什么我应该“从不给出”这些命令或“在错误的时间给出它们”?
    • 我已经尝试删除约束上的填充,它删除了警告,正如你所说,现在行高是问题所在。在这个例子中我可以手动设置高度,但在我的实际使用中,不同的单元格会有不同的高度。从概念上讲,在这个非常简单的示例中,我想说: - 图像应该距顶部 10pt,距底部 10pt,高 80pt。 - 并且单元格的高度应该在 viewController 中自动计算。为此,我只是创建了一个隐藏单元格,其目的就是为了做到这一点。
    • @RobertAtkins 不幸的是,我的回答未能指出导致此问题的关键原因之一,即 单元格分隔符具有高度。因此,如果您为单元格分配的高度不考虑单独的高度,则自动布局约束(如果是绝对的)无法解析为该高度。我已经为此效果添加了一个编辑。
    • @matt,您在 Github 404s 上的示例项目的链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 2020-07-09
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    相关资源
    最近更新 更多