如何从过滤的NSTableView中始终获取所选单元格值?

时间:2014-07-30 07:21:39

标签: objective-c cocoa nstableview nscell nssearchfield

上下文

我有一个由NSArrayController管理的2列基于单元格的NSTableView。

  • 第一列填充了复选框,以指示该值是否已启用。
  • 第二列代表元素的名称。

视图链接到NSSearchField,因此基于谓词过滤,该谓词将搜索字符串与第2列中的字符串进行比较。

在更改搜索字符串时,视图正确显示并按预期过滤。

要求

我只需要允许用户最多启用5行。为实现此目的,我正在监视后备阵列中的更改并跟踪已启用条目的数量。如果计数超过5,则我通过警报通知用户,并通过获取所选行索引然后在后备阵列中禁用该索引来取消选择先前启用的条目。我在[willChange .. ..didChange] KVO块中执行此操作。

当视图未排序时,这可以正常工作,但显然会导致问题,因为所选行不再对应于数组中的相应索引。

因此,如果视图被过滤(搜索字符串不为空),我使用以下代码来获取所选单元格的字符串值。然后我遍历数组并禁用与字符串匹配的条目。

NSInteger selectedRow = [_tv_TableView selectedRow];
NSTableColumn* column=  [_tv_TableView tableColumns][1];
NSCell* cell = [column dataCellForRow:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

问题

虽然所选行始终准确,但从代表单元格获取值不是。看来最初返回的值是正确的,但是选择其他行会返回来自下一行的数据,即使所选索引仍然正确。我还观察到它在视图中从几行返回值。

更新

在进一步测试之后,似乎第一次应用过滤器它将起作用,但是用不同的字符串过滤会保留第一个选定单元格的单元格值。

即:

  1. 加载窗口并选择6项
  2. 取消选择第6项并提醒用户
  3. 应用过滤器
  4. 选择新的第6项
  5. 取消选择第6项并提醒用户
  6. 在同一过滤器中选择不同的第6项
  7. 取消选择第6项并提醒用户
  8. 输入新过滤器
  9. 选择新的第6项
  10. 取消选择第6项并提醒用户
  11. 从同一过滤器中选择新的第6项
  12. 所选索引是正确的,但所选行的值与先前的选择相同
  13. 用户反复发出警告,因为未取消选择正确的条目,导致6个永久选择的条目。
  14. 但是,仍然会返回以下行值而不是之前选择的项目。

    问题

    我的问题是:

    1. 我是否以正确的方式获取已筛选列表的所选行?
    2. 如何根据所选行一致地检索第2列的字符串值,即使列表已排序?
    3. 感谢您的时间。

      解决方案

      我通过更改获取单元格的代码来解决这个问题:

      NSInteger selectedRow = [_tv_TableView selectedRow];
      NSTableColumn* column=  [_tv_TableView tableColumns][1];
      NSCell* cell = [column dataCellForRow:row];
      NSString* cellValue = (NSString*)[cell stringValue];
      return cellValue;
      

      要:

      NSCell* cell = [_tv_TableView preparedCellAtColumn:1 row:row];
      NSString* cellValue = (NSString*)[cell stringValue];
      return cellValue;
      

2 个答案:

答案 0 :(得分:1)

简单的解决方案是将表的selectionIndexes绑定绑定到数组控制器的同名属性。然后,您可以访问阵列控制器的-selectedObjects以查找所选对象。

如果表格中有一行(或索引),无论是否选中,您都可以使用-arrangedObjects的{​​{1}}。这将始终对应于索引。

细胞被重复使用。每个(行,列)位置都没有关联的单个单元格。每个列都有一个单元格,但每次需要绘制或以其他方式操作时,都会为每行重新配置。这就是您需要准备好的单元格的原因。也就是说,单元在概念上处于视图层(在模型 - 视图 - 控制器中)的术语中。您正在做的事情应该在控制器和模型域中,因此您不应该查看视图层(并且不应该这样做)。

答案 1 :(得分:0)

出于某种原因,在更改NSSearchField中的过滤器时,未更新项的内部表示。这是返回值不一致的值 实际观点。

我通过更改获取单元格的代码来解决这个问题:

NSInteger selectedRow = [_tv_TableView selectedRow];
NSTableColumn* column= [_tv_TableView tableColumns][1];
NSCell* cell = [column dataCellForRow:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

要:

NSCell* cell = [_tv_TableView preparedCellAtColumn:1 row:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

在此之前,我还尝试使用以下方法强制视图手动更新:

[_tv_TableView reloadData];

但这对结果没有影响。 我仍然有兴趣知道为什么会发生这种情况。如果我发现了,那我就是 更新答案。

相关问题