本文总结了 Table View 怎样处理键盘事件,以及如何通过 delegate 方法来定制其行为。
在处理某 View Controller 的键盘事件时, keyDown:
事件总是无法正确响应,因为 View Controller 中有 Table View ,每当与 Table View 交互后 Window 的 First Responder 就会变成 Table View ,而键盘事件在 Table View 中被处理并结束了。这就是 NSTableView 的 Type Selection 行为。
通过实现 Table View 的一些相关 delegate 方法就能简单轻松地定制化 Table View 的 Type Selection 行为。
为了简化表格的操作,NSTableView 通过支持 Type Selection 让用户可以使用键盘来查找或者选择 Table View 中对应的行。 在 Table View 的 keyDown:
事件中,默认会通过比较按键内容与每一行 View 的 stringValue
来查找并选择。
首先可以通过设置 Table View 的 allowsTypeSelect
属性来启用或者禁用 Type Selection(默认是启用的)。
Type Selection 通过 delegate 方法 tableView(_:typeSelectStringFor:row:)
返回的 String?
和键盘事件中按键的值比较来判断相对应要查找或选择的行。
当 delegate 没有实现 tableView(_:typeSelectStringFor:row:)
方法时,Table View 将通过 preparedCell(atColumn:row:)
返回 Cell 的 stringValue
作为查找的值。
总之 Table View 中任一一项都有相对应的可查找的值。如果需要限制 Type Selection 在 Table View 中可进行有效查找的范围,可以通过在 tableView(_:typeSelectStringFor:row:)
方法中对特定的列或者行返回 nil
来实现。
通过实现 delegate 的 tableView(_:nextTypeSelectMatchFromRow:toRow:for:)
方法可以进一步的定制 Type Selection 的行为。如果已经选中多行,该方法将在选中的行中通过与当前的 string 比较合适的值选择某一行,如果没有合适的行则返回 -1
。
此外 delegate 可以通过实现 tableView(_:shouldTypeSelectFor:withCurrentSearch:)
方法决定 Type Selection 是否响应某些特定的键盘事件。需要注意的是,在这一方法中返回 NO
仅禁止了 Type Selection 的处理,并不会就此终止键盘事件继续传递,如果实现自定义的快捷键不能在这个函数中直接进行处理,而应该重载 keyDown:
方法。
Table View 的 Type Selection 整个过程可以用伪代码描述如下:
// in NSTableView keyDown(theEvent: NSEvent) { // Pseudo-code guard allowsTypeSelect else { super.keyDown(theEvent) return } var matchRow = nil let currentSearch = theEvent.characters for row in rows { if !shouldTypeSelectForRowAndCurrentSearch { // 'true' if delegate not implement this method. continue } if let typeSelectStringAtRow == currentSearch { // using 'preparedCell.stringValue' if delegate not implement this method. matchRow = row break } } select(matchRow) }
NSTableView 及 NSTableViewDelegate 中相关的属性、方法如下:
在学习文档过程中,由于几个相关文档的版本及更新时间不一,尚有一些存在困惑的地方。上文提到:
当 delegate 没有实现 tableView(_:typeSelectStringFor:row:)
方法时,Table View 将通过 preparedCell(atColumn:row:)
返回 Cell 的 stringValue
作为查找的值。
令人不解的是此方法仅对基于 NSCell 的 Table View 有效,并且在 最新文档 中方法已标记为 Deprecated ,改为 view(atColumn:row:makeIfNecessary:)
,可无论 return 的 NSView 或 NSTableCellView 都没有 stringValue
。
在实际情况中似乎 View 和 subViews 中有 stringValue
的值都可以被 Type Selection 搜索。
因此在 delegate 没有实现 tableView(_:typeSelectStringFor:row:)
方法时 Table View 是如何获取每一行的 stringValue
并不清楚。
:leaves: That's all, Happy Coding :fallen_leaf:
SalesX 是给 Apple 开发者使用的菜单栏工具,第一时间把 app 销售情况推送给你,7 天免费试用
CurrencyX 是 Mac 上小而美的汇率 app
如果你觉得文章对你有帮助,可以买一个支持我们
关注我们公众号,获取最新文章推送