本文总结了 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 行为。
Type Selection
为了简化表格的操作,NSTableView 通过支持 Type Selection 让用户可以使用键盘来查找或者选择 Table View 中对应的行。
在 Table View 的 keyDown:
事件中,默认会通过比较按键内容与每一行 View 的 stringValue
来查找并选择。
定制化的 Type Selection
首先可以通过设置 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
并不清楚。
参考
🍃 That's all, Happy Coding 🍂
支持我们
SalesX 是给 Apple 开发者使用的菜单栏工具,第一时间把 app 销售情况推送给你,7 天免费试用
CurrencyX 是 Mac 上小而美的汇率 app
如果你觉得文章对你有帮助,可以买一个支持我们
关注我们公众号,获取最新文章推送