在具有自动布局的 UITableViewCell 中动态调整大小的 UIWebView - 违反约束

Posted

技术标签:

【中文标题】在具有自动布局的 UITableViewCell 中动态调整大小的 UIWebView - 违反约束【英文标题】:Dynamically sized UIWebView in a UITableViewCell with auto layout - constraint violation 【发布时间】:2014-05-28 00:28:44 【问题描述】:

我有一个UITableViewCell,其中包含一个UIWebView。表格视图单元格根据 Web 视图内容调整其高度。 我一切正常,但是当视图加载时,我在调试器中遇到约束冲突异常(应用程序继续运行并且功能正常,但如果可能,我想解决此异常)。

我是如何设置的:

TableView 像这样设置单元格高度:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    if(indexPath.section == 0) 
        [_topCell layoutIfNeeded];
        CGFloat finalHeight =  [_topCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
        return finalHeight + 1;
    

单元格约束如下:

    从单元格的 contentView(顶部)到 webView 的任意 7px 偏移 Web 视图具有 62 像素的任意固定高度限制(稍后将在内容加载后展开) 从 webView 到单元格的 contentView 的任意 8px 偏移(底部)

在我的 viewDidLoad 中,我告诉 webView 去加载一个 URL,在 webViewDidFinishLoad 中,我更新了 web 视图的高度约束,像这样

-(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];

异常如下所示:

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 )>

这似乎有点奇怪。这意味着设置 web 视图高度的约束将被打破,但是 web 视图确实正确设置了它的高度,并且 tableview 呈现得非常好。

根据我的猜测,看起来新增加的 Web 视图高度约束(在 Web 视图加载后大约 500 像素)将与 &lt;NSAutoresizingMaskLayoutConstraint:0x10967c210 h=--&amp; v=--&amp; V:[cellContent(78)] 将单元格高度设置为 78(由界面生成器放置在那里)发生冲突。这是有道理的,但是我不希望单元格内容具有 78px 的固定高度,我希望它增加它的高度,并且在功能上,它实际上是这样做的,只是有这些例外。

我尝试设置 _topCell.contentView.translatesAutoresizingMaskIntoConstraints = NO; 以尝试删除 NSAutoresizingMaskLayoutConstraint - 这会阻止异常,但随后所有其他布局都被搞砸了,Web 视图在表格视图中间高约 10 像素没有理由。

我也尝试在 viewDidLoad 中设置 _topCell.contentView.autoresizingMask |= UIViewAutoresizingFlexibleHeight; 以希望影响 contentView 78px 高度约束,但这没有效果

任何帮助将不胜感激

【问题讨论】:

您的[_topCell layoutSubviews]; 中有什么内容? 我所做的工作与您所做的完全相同。如果您对此有解决方案,能否与我分享一些关键点?谢谢! 【参考方案1】:

另一种答案,最终要简单得多:

将 webViewHeight 约束的优先级设置为非必需。运行良好,没有警告。我建议使用这个:-)

【讨论】:

【参考方案2】:

我想出了一个解决方案。这看起来像是一个 hack,但它可以正常工作并且不会产生错误和警告。

诀窍是将 Web 视图的布局和高度与 contentView 分离。

我是这样做的:

    在tableviewcell中,添加一个新的UIView,名为containerView 为 Top:0 Left:0 Right:0 设置约束,但没有底部约束和高度约束 将 Web 视图(和任何其他内容)放入此 containerView 添加约束,使 Web 视图距 containerView 的顶部和底部 7 像素,并且高度约束为 62 像素

此时,containerView 没有连接到表格视图单元格的底部,因此它可能会溢出/不足而不会抱怨自动布局。

现在,在tableView:heightForRowAtIndexPath: 中,我们根据containerView 计算单元格高度如下:

-(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];

全部完成!

【讨论】:

【参考方案3】:

来自约束日志

你想要达到的约束如下,

在一个 78 px 的 cellContentHeight 中,您想要容纳 7(顶部空间)+ 62(Web 视图)+ 8(底部空间)的内容。这是 77(不等于 78)。两个选项中的任何一个都可以,

    尝试将上边距设为 8(而不是 7)并将其设为 78。(V:|-8-[WebView(62)]-8-|) 附加到顶部,提供 8 像素顶部空间 (V:|-8-[WebView(62)]) 并且不指定 8 像素底部空间。 附加到底部,提供 8 像素底部空间 (V:[WebView(62)-8-|) 并且不指定顶部空间。

【讨论】:

是的,我同意,但是我在界面生成器中将单元格高度设置为 77。 UIKit 正在从某个地方生成内容视图 78px 约束,我不知道为什么

以上是关于在具有自动布局的 UITableViewCell 中动态调整大小的 UIWebView - 违反约束的主要内容,如果未能解决你的问题,请参考以下文章

在具有自动布局的 UITableViewCell 中动态调整大小的 UIWebView - 违反约束

具有自动布局约束的 UITableViewCell 子类大小不正确

是啥导致两个具有相同自动布局约束的 UITableViewCell 表现不同?

UITableViewCell 具有嵌入式垂直堆栈视图设置,具有自动布局和动态高度

具有自动布局左边距的 UITableViewCell 在 iPhone 和 iPad 上不同

视图中具有多个单元格标识符的自动布局 UITableViewCell