在具有自动布局的 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 像素)将与 <NSAutoresizingMaskLayoutConstraint:0x10967c210 h=--& v=--& 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 具有嵌入式垂直堆栈视图设置,具有自动布局和动态高度