您正在iOS8的Tableviews中遇到一个奇妙的新功能的副作用:自动行高。
在iOS 7中,您要么拥有固定大小的行(设置为tableView.rowHeight),要么编写代码以计算单元格的高度,然后将其返回tableView:heightForRowAtIndexPath。如果您在单元格中有许多视图并且在不同字体大小下需要考虑不同的高度,那么编写用于计算单元格高度的代码可能会非常复杂。添加“动态类型”后,整个过程变得很痛苦。
在iOS 8中,您仍然可以执行上述操作,但是现在行的高度可以由iOS确定,前提是您已使用“自动布局”配置了单元格的内容。这对开发人员来说是巨大的好处,因为随着动态字体大小的变化或用户使用“辅助功能设置”修改文本大小,您的UI可以适应新的大小。这也意味着,如果您有一个可以包含多行文本的UILabel,则您的单元格现在可以增长以容纳需要的单元格,而当单元格不需要时可以收缩,因此没有任何不必要的空格。
您看到的警告消息告诉您,单元格中没有足够的约束来使自动版式通知表格视图单元格的高度。
要使用动态单元格高度(它与其他发布者已经提到的技术一起使用)也将摆脱此消息,您需要确保您的单元格具有足够的约束来将UI项绑定到单元格的顶部和底部。如果您以前使用过“自动布局”,则可能习惯于设置“顶部+前导”约束,但是动态行高还需要底部约束。
布局遍历是这样工作的,它以即时的方式立即在屏幕上显示单元之前发生:
计算具有内在尺寸的内容的尺寸。这包括UILabels和UIImageViews,它们的尺寸分别基于它们包含的文本或UIImages。这两个视图都将认为它们的宽度是已知的(因为您已经设置了后沿/前缘的约束,或者设置了显式宽度,或者使用了水平约束最终显示了左右的宽度)。假设标签上有一段文字(“行数”设置为0,所以它将自动换行),它只能跨310磅,因此确定为当前字体大小时高120pt。
用户界面根据您的定位限制进行布局。标签底部有一个约束,该约束连接到单元格的底部边缘。由于标签的高度已增加到120点,并且由于约束已绑定到单元格的底部,因此标签必须“向下”推动单元格(增加单元格的高度),以满足表示“底部”的约束。标签始终是与单元格底部的标准距离。
如果缺少该底部约束,则会发生您报告的错误消息,在这种情况下,没有什么可“推”该单元格的底部使其远离该单元格的顶部,这是所报告的歧义:没有东西可将底部推离顶部,单元崩溃。但是“自动版式”也会检测到这一点,并退回到使用标准行高。
对于它的价值,并且通常需要一个综合的答案,如果您确实实现了iOS 8的基于Auto Layout的动态行高,则应该实现tableView:estimatedHeightForRowAtIndexPath:。该估计方法可以为您的单元格使用粗略值,并且在最初加载表格视图时会调用它。它可以帮助UIKit绘制滚动条之类的东西,除非表视图知道它可以滚动多少内容,否则它就无法绘制,因为它只是滚动条,因此不需要完全准确的大小。这样就可以将实际行高的计算推迟到需要该单元格的那一刻为止,这将减少计算强度,并可以更快地显示UITableView。