Я нашел, что это работает, если:
0) Создать структуру для простого построения UIKeyCommands
struct keyCommand {
var input: String;
var modifiers: UIKeyModifierFlags
}
`1) подкласс UIWIndow 2) Вы переопределяете переменную keyCommands в «окне сцены» и создайте ключевые команды для каждого ключа, который вы хотите, чтобы окно захватывало. Мое приложение имеет несколько сцен, поэтому сохраненная строка идентификатора сцены используется для показа текущей фокусировки (первый респондент)
class Window: UIWindow{
var model: CCModel! // will load after the window established
var app: AppDelegate!
var scene: String!
var keyCommandList: [keyCommand]
var commands: [UIKeyCommand]?
override init(frame: CGRect) {
keyCommandList = [
//arrow keys
keyCommand(input: UIKeyCommand.inputUpArrow, modifiers:[]),
keyCommand(input: UIKeyCommand.inputUpArrow, modifiers:.alternate),
keyCommand(input: UIKeyCommand.inputUpArrow, modifiers:.command),
keyCommand(input: UIKeyCommand.inputUpArrow, modifiers: .shift),
keyCommand(input: UIKeyCommand.inputDownArrow, modifiers:[]),
keyCommand(input: UIKeyCommand.inputDownArrow, modifiers:.alternate),
keyCommand(input: UIKeyCommand.inputDownArrow, modifiers:.command),
keyCommand(input: UIKeyCommand.inputDownArrow, modifiers: .shift),
keyCommand(input: UIKeyCommand.inputLeftArrow, modifiers:[]),
keyCommand(input: UIKeyCommand.inputLeftArrow, modifiers:.alternate),
keyCommand(input: UIKeyCommand.inputLeftArrow, modifiers:.command),
keyCommand(input: UIKeyCommand.inputLeftArrow, modifiers: .shift),
keyCommand(input: UIKeyCommand.inputRightArrow, modifiers:[]),
keyCommand(input: UIKeyCommand.inputRightArrow, modifiers:.alternate),
keyCommand(input: UIKeyCommand.inputRightArrow, modifiers:.command),
keyCommand(input: UIKeyCommand.inputRightArrow, modifiers: .shift),
//escape
keyCommand(input: UIKeyCommand.inputEscape, modifiers: []),
// a (play arpegio), A - progression arpegio
keyCommand(input: "a", modifiers: []),
keyCommand(input: "a", modifiers: .shift),
// c (play chord), S - progression chord
keyCommand(input: "c", modifiers: []),
keyCommand(input: "c", modifiers: .shift),
// tab key,
keyCommand(input: "\t", modifiers: []),
keyCommand(input: "\t", modifiers: .shift),
// return
keyCommand(input: "\r", modifiers: []),
keyCommand(input: "\r", modifiers: .shift),
// +
keyCommand(input: "+", modifiers: []),
keyCommand(input: "=", modifiers: []),
// -
keyCommand(input: "-", modifiers: []),
keyCommand(input: "_", modifiers: []),
// space
keyCommand(input: " ", modifiers: []),
keyCommand(input: "0", modifiers: []), // toggle the accents
keyCommand(input: "p", modifiers: []),
keyCommand(input: "s", modifiers: []),
keyCommand(input: "s", modifiers: .alternate),
keyCommand(input: "s", modifiers: .command),
keyCommand(input: "i", modifiers: []),
keyCommand(input: "k", modifiers: []),
keyCommand(input: "?", modifiers: []),
keyCommand(input: "t", modifiers: []),
keyCommand(input: "r", modifiers: []),
keyCommand(input: "o", modifiers: []),
keyCommand(input: "d", modifiers: []),
keyCommand(input: "w", modifiers: []),
keyCommand(input: "h", modifiers: []),
keyCommand(input: "l", modifiers: []),
keyCommand(input: "1", modifiers: []),
keyCommand(input: "2", modifiers: []),
keyCommand(input: "3", modifiers: []),
keyCommand(input: "4", modifiers: []),
keyCommand(input: "5", modifiers: []),
]
self.commands = []
for command in self.keyCommandList {
let keycommand = UIKeyCommand(input: command.input, modifierFlags: command.modifiers, action: #selector(self.captureKey(sender:)))
self.commands!.append(keycommand)
}
super.init(frame: frame)
open override var keyCommands: [UIKeyCommand]? {
return self.commands
}
@objc func captureKey(sender: UIKeyCommand) {
self.model.onKeyCapture(sender, scene: self.scene)
}
}
3) Отправьте захваченный ключ и модификаторы делегату для управления им. , В моем случае это методы self.model.method. (модель - это класс-одиночка для этого приложения).
func onKeyCapture(_ sender: UIKeyCommand, scene: String) {
let app = getApp()
let input = sender.input
let modifiers = sender.modifierFlags
if scene == "main" {
// handle main screen key commands
// mode independent commands
switch input {
case "k","1":
setMode(value: "C")
selectSegment(0)
return
case "s","2":
if modifiers == [] { // allow modified "s" through
setMode(value: "S")
selectSegment(1)
return
}
case "i","?","3":
setMode(value: "I")
selectSegment(2)
return
case "p","4":
setMode(value: "P")
selectSegment(3)
return
default:
break
}
switch input {
case "t":
switch modifiers {
case []:
playTuning()
return
default:
break
}
default:
break
}
switch mode {
case "C": // chord mode
switch input {
case UIKeyCommand.inputUpArrow:
switch modifiers {
case []:
nextPrev(type: .prev)
default:
break
}
case UIKeyCommand.inputDownArrow:
switch modifiers {
case []:
nextPrev(type: .next)
default:
break
}
case UIKeyCommand.inputRightArrow:
switch modifiers {
case []:
app.chordTVC!.setbyKeyCommand(delta: +1)
default:
break
}
case UIKeyCommand.inputLeftArrow:
switch modifiers {
case []:
app.chordTVC!.setbyKeyCommand(delta: -1)
default:
break
}
case " ":
toggleShowChordScale()
case "0":
app.fretboardVC!.toggleAccents()
case "c":
switch modifiers {
case []:
playChord()
default:
break
}
case "a":
switch modifiers {
case []:
playArpeggio()
default:
break
}
case "+","=":
if root == nil { // no root chosen, so set it to "C"
app.rootTVC!.setRootByValue(key: "C")
} else { // raise the key a semitone
incrementDecrementKey(direction: 1)
}
case "-","_":
if root == nil { // no root chosen, so set it to "C"
app.rootTVC!.setRootByValue(key: "C")
} else { // lower the key a semitone
incrementDecrementKey(direction: -1)
}
case "r":
app.filtersCVC!.toggleFilter("NOROOT_OK")
case "5":
app.filtersCVC!.toggleFilter("NO5TH_OK")
case "o":
app.filtersCVC!.toggleFilter("NO_OPEN")
case "d":
app.filtersCVC!.toggleFilter("NO_DEAD")
case "w":
app.filtersCVC!.toggleFilter("NO_WIDOW")
case "h":
app.filtersCVC!.toggleHighLow("high")
case "l":
app.filtersCVC!.toggleHighLow("low")
default:
break
}
case "S": // Scale mode
switch input {
case UIKeyCommand.inputRightArrow:
switch modifiers {
case []:
app.scaleTVC!.setbyKeyCommand(delta: +1)
default:
break
}
case UIKeyCommand.inputLeftArrow:
switch modifiers {
case []:
app.scaleTVC!.setbyKeyCommand(delta: -1)
default:
break
}
case "+","=":
if root == nil { // no root chosen, so set it to "C"
app.rootTVC!.setRootByValue(key: "C")
} else { // raise the key a semitone
incrementDecrementKey(direction: 1)
}
case "-","_":
if root == nil { // no root chosen, so set it to "C"
app.rootTVC!.setRootByValue(key: "C")
} else { // lower the key a semitone
incrementDecrementKey(direction: -1)
}
case " ":
switch modifiers {
case []: // two finger tap equivalent
if scaleDisplayMode == "notes" {
scaleDisplayMode = "tones"
} else {
scaleDisplayMode = "notes"
}
FretboardNeedsDisplay()
default:
break
}
case "a":
showAccents = !showAccents
FretboardNeedsDisplay()
case "\r":
if modifiers == []{
playScale()
}
default:
break
}
case "I": // Identify mode
switch input {
default:
break
}
case "P": // Progression mode
switch input {
case UIKeyCommand.inputUpArrow:
switch modifiers {
case []:
nextPrev(type: .prev)
default:
break
}
case UIKeyCommand.inputDownArrow:
switch modifiers {
case []:
nextPrev(type: .next)
default:
break
}
case UIKeyCommand.inputRightArrow: // next previous progression
switch modifiers {
case []:
app.progDisplayTVC!.setbyKeyCommand(delta: +1)
default:
break
}
case UIKeyCommand.inputLeftArrow:
switch modifiers {
case []:
app.progDisplayTVC!.setbyKeyCommand(delta: -1)
default:
break
}
case " ":
toggleShowChordScale()
case "0":
app.fretboardVC!.toggleAccents()
case "c":
switch modifiers {
case []:
playChord()
case .shift:
progPlayChord()
default:
break
}
case "a":
switch modifiers {
case []:
playArpeggio()
case .shift:
progPlayArp()
default:
break
}
case "+","=":
if root == nil { // no root chosen, so set it to "C"
app.rootTVC!.setRootByValue(key: "C")
} else { // raise the key a semitone
incrementDecrementKey(direction: 1)
}
case "-","_":
if root == nil { // no root chosen, so set it to "C"
app.rootTVC!.setRootByValue(key: "C")
} else { // lower the key a semitone
incrementDecrementKey(direction: -1)
}
case "r":
app.filtersCVC!.toggleFilter("NOROOT_OK")
case "5":
app.filtersCVC!.toggleFilter("NO5TH_OK")
case "o":
app.filtersCVC!.toggleFilter("NO_OPEN")
case "d":
app.filtersCVC!.toggleFilter("NO_DEAD")
case "w":
app.filtersCVC!.toggleFilter("NO_WIDOW")
case "h":
app.filtersCVC!.toggleHighLow("high")
case "l":
app.filtersCVC!.toggleHighLow("low")
default:
break
}
default:
break
}
}
else if scene == "help" {
// handle help screen key commands
}
}