具有自动布局的自定义UITableViewCell会导致警告

时间:2014-12-14 18:43:51

标签: ios objective-c uitableview ios8

对于我的项目,我需要显示包含大量信息的医生列表,为此我以编程方式创建自定义单元格。以下是我的单元格视图的结构:

Cell.contentView
  | --> UIView
    | --> UILabel (Title)
    | --> UILabel (Subtitle)
    | --> UIView (a simple separator, with a 1px height constraint)
    | --> UILabel (Address, multilines)

这是我真正拥有的简化结构,但它足以带来警告。

这是警告:

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:0x14f9a790 V:|-(11)-[UILabel:0x16058ea0'DR.NAME']   (Names: '|':DoctorHealthInformationView:0x16058f70 )>",
    "<NSLayoutConstraint:0x14f86300 V:[UILabel:0x16058ea0'DR.NAME']-(1.5)-[UILabel:0x160670e0'Chirurgien Dentiste']>",
    "<NSLayoutConstraint:0x14f86390 V:[UILabel:0x160670e0'Specialty']-(9)-[UIView:0x14e0fde0]>",
    "<NSLayoutConstraint:0x14f9ab20 V:[UIView:0x14e0fde0]-(8)-[KDCellLabel:0x14f90d10'Address\naddres...']>",
    "<NSLayoutConstraint:0x14f9ab50 KDCellLabel:0x14f90d10'Address\naddres...'.bottom == DoctorHealthInformationView:0x16058f70.bottom - 10>",
    "<NSLayoutConstraint:0x14f97a80 V:|-(0)-[DoctorHealthInformationView:0x16058f70]   (Names: '|':CustomDoctorCell:0x1605a890'OnlineCustomDoctorCell' )>",
    "<NSLayoutConstraint:0x14f88840 V:[DoctorHealthInformationView:0x16058f70]-(0)-[UIView:0x14f930d0]>",
    "<NSLayoutConstraint:0x14f889b0 V:[UIView:0x14f930d0(1)]>",
    "<NSLayoutConstraint:0x14f9ae10 UIView:0x14f9d330.bottom == CustomDoctorCell:0x1605a890'OnlineCustomDoctorCell'.bottom>",
    "<NSLayoutConstraint:0x14f9b120 V:[UIView:0x14f9d330(4)]>",
    "<NSLayoutConstraint:0x14f9af40 V:[UIView:0x14f930d0]-(0)-[UIView:0x14f9d330]>",
    "<NSLayoutConstraint:0x14f93020 'UIView-Encapsulated-Layout-Height' V:[CustomDoctorCell:0x1605a890'OnlineCustomDoctorCell'(44)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x14f86390 V:[UILabel:0x160670e0'Specialty']-(9)-[UIView:0x14e0fde0]>

我的约束:

我唯一的高度限制是在我的分隔符视图上,标签被所有边固定到superview,以允许我的单元格高度通过自动布局计算。如果我删除分隔符视图并将地址标签的顶部直接固定到字幕标签的底部,则警告消失。如果我在一个标签上添加高度约束,则会返回警告。

一些经典但有趣的方法:

获取指定行的高度:

TableViewController:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    Doctor *doctor = (Doctor *)[_doctorsToShow objectAtIndex:indexPath.row];
    static CustomDoctorCell *sizingCellClassic = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sizingCellClassic = [[CustomDoctorCell alloc] initWithStyle:UITableViewCellStyleDefault
                                                    reuseIdentifier:classicDoctorCellIdentifier
                                                          forDoctor:doctor
                                                      showSpecialty:YES
                                               withAppointmentStyle:YES];
    });

    [sizingCellClassic updateContentForDoctor:doctor];
    return [CustomDoctorCell getCellHeightForCell:sizingCellClassic];
}

CustomDoctorCell:

+ (float) getCellHeightForCell:(CustomDoctorCell *)doctorCell
{
    [doctorCell setNeedsLayout];
    [doctorCell layoutIfNeeded];

    CGSize size = [doctorCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    return size.height;
}

我不明白我做错了什么,以及要删除此警告我必须做些什么,我尝试下载this example表单raywenderlich.com并简单地添加标签上的高度限制,我得到了同样的警告。

还有一件事,我必须与ios 7完全兼容,这就是为什么我没有使用sdk 8引入的新功能。

2 个答案:

答案 0 :(得分:2)

在故事板中使用原型单元时,我遇到了类似的情况;内容视图的UIView-Encapsulated-Layout-Height将所有内容都搞砸了。我的解决方案是做两件事:

首先,我将其中一个垂直约束的优先级设置为999。

其次,我设置了一个&#34; custom&#34; IB中表视图单元格的行高。

Custom Row Height

在我的情况下,它设置为266,但我不认为这真的很重要,只要你有&#34; Custom&#34;选中复选框并且它不会说&#34;默认&#34;在行高输入中。

我最初担心较低优先级的垂直间隔约束意味着手动输入的自定义高度优先,但它没有。表格单元符合我给它的约束。

这似乎违反直觉,但我的预感是,有一些预先计算会导致自定义高度和contentView内的垂直约束之间发生冲突,但是在图层点,也许在layoutSubviews中,约束优先,应用程序欢快地开展业务。因此,我认为该应用程序会查看所有内容,尝试打破约束以安抚rowHeight或estimatedRowHeight,然后回圈并执行它应该首先执行的操作。不过,这是一个完整的猜测。无论如何,它适用于我的情况。

你提到你的目标是iOS7,所以我不确定它是否适合你,因为我只在iOS8中测试过,但我们的情况非常相似,这可能值得一试。鉴于它是iOS8,我使用了新的功能。

    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.estimatedRowHeight = (UIApplication.sharedApplication().keyWindow?.bounds.height)! * (460.0/1334.0)

答案 1 :(得分:1)

单元格的初始高度可能小于垂直约束。这会产生初始高度冲突,直到contentView的帧发生变化。

您可以使用以下方法之一解决此问题:

  • 在故事板中增加单元格的高度,使其最初适合内容。

  • 将单元格内容视图的边界更改为更大的尺寸:

    self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);

您可以在this auto layout question的答案中找到更多详细信息。