上下文
我有一个由 NSArrayController 管理的 2 列、基于单元格的 NSTableView。
- 第一列填充了复选框,指示该值是否已启用。
- 第二列代表元素的名称。
该 View 链接到 NSSearchField,因此根据将搜索字符串与第 2 列中的字符串进行比较的谓词进行过滤。
当搜索字符串更改时, View 可以正确显示并按预期进行过滤。
要求
我只需要允许用户启用最多 5 行。为了实现这一目标,我正在监视支持阵列的更改并跟踪启用的条目的数量。如果计数超过 5,那么我会向用户发出警报,并通过获取选定的行索引来取消选择之前启用的条目,然后在支持数组中禁用该索引。我在 [willChange...didChange] KVO block 中执行此操作。
当 View 未排序时,这会按预期工作,但显然会导致问题,因为所选行不再对应于数组中的适当索引。
因此,如果 View 被过滤(搜索字符串不为空),我使用以下代码来获取所选单元格的字符串值。然后我遍历数组并禁用与字符串匹配的条目。
NSInteger selectedRow = [_tv_TableView selectedRow];
NSTableColumn* column= [_tv_TableView tableColumns][1];
NSCell* cell = [column dataCellForRow:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;
问题
尽管选定的行始终是准确的,但从代表单元格获取值却并非如此。看起来最初返回的值是正确的,但随后选择其他行会返回下一行的数据,即使所选索引仍然正确。我还观察到它从 View 中的几行返回值。
更新
经过进一步测试,第一次应用过滤器时,它会起作用,但通过不同的字符串进行过滤会保留该特定错误的第一个选定单元格的单元格值。
即:
- 加载窗口并选择 6 项
- 取消选择第 6 项并警告用户
- 应用过滤器
- 选择新的第 6 项
- 取消选择第 6 项并警告用户
- 在同一过滤器中选择不同的第 6 项
- 取消选择第 6 项并警告用户
- 输入新过滤器
- 选择新的第 6 项
- 取消选择第 6 项并警告用户
- 从同一过滤器中选择新的第 6 项
- 所选索引正确,但所选行的值与先前选择的值相同
- 由于未取消选择正确的条目,导致用户多次收到警告,导致 6 个条目被永久选中。
但是,仍然存在返回以下行值的情况,但它不是先前选择的项目。
问题
我的问题是:
- 我是否以正确的方式获取筛选列表中的选定行?
- 即使列表已排序,如何根据所选行一致地检索第 2 列的字符串值?
感谢您的宝贵时间。
解决方案
我通过更改获取单元格的代码解决了这个问题:
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;
最佳答案
简单的解决方案是将表的 selectionIndexes
绑定(bind)到数组 Controller 的同名属性。然后,您可以访问数组 Controller 的 -selectedObjects
来查找选定的对象。
当表中有一行(或索引)时,无论是否选择它,都可以使用 NSArrayController
的 -arrangedObjects
。这将始终与索引相对应。
细胞被重复使用。没有与每个(行、列)位置关联的单个单元格。每列都有一个关联的单元格,但每次需要绘制或以其他方式操作行时,都会为每行重新配置该单元格。这就是为什么您需要准备好的单元格。也就是说,单元在概念上处于 View 层(模型- View - Controller )术语。您正在做的事情应该在 Controller 和模型域中,因此您不应该咨询 View 层(也不应该需要)。
关于objective-c - 如何从过滤的 NSTableView 中一致地获取选定的单元格值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25030928/