调用reloadData时NSTableView的不满意约束

时间:2013-01-04 21:14:48

标签: cocoa nstableview osx-mountain-lion autolayout

我有一个基于视图的NSTableView,其中包含表视图的NSTableCellView的设置,通过10.8.2上最新版本的Xcode中的界面构建器进行图形化。

当我在NSTableView上调用-reloadData时,它会崩溃:

Unable to simultaneously satisfy constraints:
(
    "<NSAutoresizingMaskLayoutConstraint:0x105cb8bf0 h=--& v=--& V:[NSTableRowView:0x105ca7020(0)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x10596aa30 h=--& v=-&- V:[GroupTableRowView]-(2)-|   (Names: GroupTableRowView:0x100185860, '|':NSTableRowView:0x105ca7020 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x1058d9770 h=--& v=-&- V:|-(1)-[GroupTableRowView]   (Names: GroupTableRowView:0x100185860, '|':NSTableRowView:0x105ca7020 )>"
)

Will attempt to recover by breaking constraint 
<NSAutoresizingMaskLayoutConstraint:0x10596aa30 h=--& v=-&- V:[GroupTableRowView]-(2)-|   (Names: GroupTableRowView:0x100185860, '|':NSTableRowView:0x105ca7020 )>

我无法关闭所涉及的任何视图上的自动调整大小掩码转换,因为它们的约束由NSTableView管理。很明显,约束是冲突的,因为NSTableRowView不可能具有0高度,同时仍然满足GroupTableRowView上的其他两个约束,这些约束指定了superview(行视图?)之间的强制填充。我不知道如何解决这个问题,我们将非常感谢任何见解。谢谢!

更新: 我找到了一个解决方法。问题是,由于某种原因,在表视图上调用-reloadData时,NSTableRowView的帧大小为{0, 0}。我覆盖了NSTableRowView子类中的-setFrameSize:,并且只在大小不是{0,0}时才将消息传递给响应者链。

- (void)setFrameSize:(NSSize)newSize
{
    if (!NSEqualSizes(newSize, NSZeroSize))
        [super setFrameSize:newSize];
}

要使用子类,请实现NSTableViewDelegate的-tableView:rowViewForRow:方法以返回自定义子类的实例。

- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
{
    id rowView = [[GroupTableRowView alloc] init];
    // configure any custom properties
    return rowView;
}

如果表视图完全在IB中设计,您只需将新的NSView拖到表视图中,并将其自定义类设置为NSTableRowView子类,并将其用户界面项标识符更改为NSTableViewRowViewKey

2 个答案:

答案 0 :(得分:1)

我有同样的问题,它总是让我疯狂..

我已经使用您的代码解决了这个问题,但是继承了NSTableRowView而不是NSTableCellView。要自动让表格使用自定义行视图,请在表格中添加自定义NSView。将其类设置为自定义行视图,重要的是将其标识符设置为NSTableViewRowViewKey

使用此特殊标识符,表格会自动将其用作行视图。

答案 1 :(得分:1)

我有类似的问题,但是列宽而不是行高。调用NSTableView后立即在基于视图的reloadData的单元格上弹出不满意的自动布局约束。就我而言,它是由NSTableColumn上的最小宽度设置太小而不能包含单元格中约束的最小宽度引起的。所以对于有类似问题的人,我会首先验证一下。

“有趣”的部分是这只是reloadData的一个问题,而不是普通的布局,因为NSTableView的宽度受到限制,导致它无法正常尝试创建一个小的细胞。但是当调用reloadData时,它显然首先创建一个新的单元格,其框架大小设置为最小列宽,然后再调整列大小以适应(如果您设置了表格)。因此,即使一切看起来都运行正常,但在调用reloadData之后仍然会出现关于不可满足约束的错误,因为单元格视图的初始宽度对于填充等来说太小了。

故事的道德是始终检查最小 NSTableColumn宽度对于单元格中的约束是否足够大,即使您认为列不会是那样的小。 IB可以很容易地修改约束,并且在更改单元格中的内容后很容易忘记重新检查列宽选项。