Cacao scelte rapide da Tastiera nella finestra di Dialogo senza un Menu Modifica

Ho un LSUIElement applicazione che visualizza una barra di stato. L’applicazione in grado di visualizzare una finestra di dialogo che contiene un campo di testo.

Se l’utente fa/di controllo-fa clic sul campo di testo, viene visualizzato un menu che consente di tagliare, copiare, incollare, ecc. Tuttavia, il Comando standard X, Comando-C, e il Comando-V scorciatoie da tastiera non funzionano in campo. Presumo che questo è perché la mia applicazione non fornisce un menu Modifica con quei tasti definite.

Ho provato ad aggiungere una voce di menu Modifica per il mio menu dell’applicazione, come suggerito nel Nave Un Po ‘ Di Codice blog, ma che non ha funzionato. Le voci di menu nel menu di Modifica può essere utilizzato, ma le scorciatoie da tastiera non funzionano.

Posso immaginare un paio di modi per hackerare la gestione della tastiera, ma c’è un “raccomandato” modo di fare questo lavoro?

(Per i dettagli sull’app, vedere Menubar Conto Alla Rovescia.)

Domanda correlata: Copia/Incolla Non funziona in Finestra Modale



15 Replies
  1. 42

    Migliorando CocoaRocket soluzione:

    Seguente modo sottoclasse NSTextField e ricordando di utilizzare il sottoclasse in tutta l’applicazione; ciò permette anche di copiare, incollare e amici per altri soccorritori che li gestiscono, ad esempio. NSTextView.

    Mettere questo in una sottoclasse di NSApplication e modificare la classe principale nella vostra Info.plist di conseguenza.

    - (void) sendEvent:(NSEvent *)event {
        if ([event type] == NSKeyDown) {
            if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) == NSCommandKeyMask) {
                if ([[event charactersIgnoringModifiers] isEqualToString:@"x"]) {
                    if ([self sendAction:@selector(cut:) to:nil from:self])
                        return;
                }
                else if ([[event charactersIgnoringModifiers] isEqualToString:@"c"]) {
                    if ([self sendAction:@selector(copy:) to:nil from:self])
                        return;
                }
                else if ([[event charactersIgnoringModifiers] isEqualToString:@"v"]) {
                    if ([self sendAction:@selector(paste:) to:nil from:self])
                        return;
                }
                else if ([[event charactersIgnoringModifiers] isEqualToString:@"z"]) {
                    if ([self sendAction:@selector(undo:) to:nil from:self])
                        return;
                }
                else if ([[event charactersIgnoringModifiers] isEqualToString:@"a"]) {
                    if ([self sendAction:@selector(selectAll:) to:nil from:self])
                        return;
                }
            }
            else if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSShiftKeyMask)) {
                if ([[event charactersIgnoringModifiers] isEqualToString:@"Z"]) {
                    if ([self sendAction:@selector(redo:) to:nil from:self])
                        return;
                }
            }
        }
        [super sendEvent:event];
    }
    
    //Blank Selectors to silence Xcode warnings: 'Undeclared selector undo:/redo:'
    - (IBAction)undo:(id)sender {}
    - (IBAction)redo:(id)sender {}
    • Soluzione perfetta! Un altro aspetto negativo dell’originale era che dovresti ridefinire le sottoclassi di NSTextField troppo, come NSSearchField.
    • Ho modificato per includere rifare.
    • Inoltre ho dovuto sostituire NSApplication con il mio sottoclasse nella main.m
    • Mentre non mi piace l’idea della creazione di sottoclassi NSApplication, questo codice funziona bene. La mia app è senza xib e un mainmenu, e ogni volta che ho provato ad aggiungere un NSTextField come sottoview a una finestra senza bordi, nessuno dei cmd scorciatoie avrebbe funzionato (ho anche superato canBecomeKeyWindow).
    • Grazie Adrian, funziona come un fascino, voglio solo prendere un avviso che il mio Xcode problemi 2 avvisi di selezione (annulla:) e selettore (rifare:) non sono riconosciuti, ma che in realtà il lavoro in fase di runtime, basta ignorare gli avvertimenti. Penso che il mio avviso potrebbe aiutare qualcuno
    • Ho appena aggiunto un paio di vuoto di selettori per il silenzio Xcode avvertenze.
    • Questo non funziona quando il Blocco maiuscole è attivato. È necessario togliere il Caps Lock bandiera prima di confrontare la parità con il comando o il comando-maiusc.

  2. 29

    Cosa ha funzionato per me è stato utilizzando La Soluzione View presentato in Copiare e Incollare le Scorciatoie da Tastiera a CocoaRocket.

    Fondamentalmente, questo significa la creazione di sottoclassi NSTextField e prevalente performKeyEquivalent:.

    Aggiornamento: Il CocoaRocket sito è andato apparentemente. Ecco l’Internet Archive link: http://web.archive.org/web/20100126000339/http://www.cocoarocket.com/articles/copypaste.html

    Modifica: La Swift codice simile a questo

    class Editing: NSTextField {
    
      private let commandKey = NSEventModifierFlags.CommandKeyMask.rawValue
      private let commandShiftKey = NSEventModifierFlags.CommandKeyMask.rawValue | NSEventModifierFlags.ShiftKeyMask.rawValue
      override func performKeyEquivalent(event: NSEvent) -> Bool {
        if event.type == NSEventType.KeyDown {
          if (event.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == commandKey {
            switch event.charactersIgnoringModifiers! {
            case "x":
              if NSApp.sendAction(Selector("cut:"), to:nil, from:self) { return true }
            case "c":
              if NSApp.sendAction(Selector("copy:"), to:nil, from:self) { return true }
            case "v":
              if NSApp.sendAction(Selector("paste:"), to:nil, from:self) { return true }
            case "z":
              if NSApp.sendAction(Selector("undo:"), to:nil, from:self) { return true }
            case "a":
              if NSApp.sendAction(Selector("selectAll:"), to:nil, from:self) { return true }
            default:
              break
            }
          }
          else if (event.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == commandShiftKey {
            if event.charactersIgnoringModifiers == "Z" {
              if NSApp.sendAction(Selector("redo:"), to:nil, from:self) { return true }
            }
          }
        }
        return super.performKeyEquivalent(event)
      }
    }

    Edit: Swift 3 codice simile a questo

    class Editing: NSTextView {
    
    private let commandKey = NSEventModifierFlags.command.rawValue
    private let commandShiftKey = NSEventModifierFlags.command.rawValue | NSEventModifierFlags.shift.rawValue
    
    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        if event.type == NSEventType.keyDown {
            if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
                switch event.charactersIgnoringModifiers! {
                case "x":
                    if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
                case "c":
                    if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
                case "v":
                    if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
                case "z":
                    if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
                case "a":
                    if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
                default:
                    break
                }
            }
            else if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
                if event.charactersIgnoringModifiers == "Z" {
                    if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
                }
            }
        }
        return super.performKeyEquivalent(with: event)
     }
    }
    • Una rapida 2.2 soluzione è risposto qui.
    • Ma questo non funziona con le altre lingue 🙁 Basta usare event.keyCode invece event.charactersIgnoringModifiers
    • Questo non funziona quando il Blocco maiuscole è attivato. È necessario togliere il Caps Lock bandiera prima di confrontare la parità con il comando o il comando-maiusc.
  3. 14

    Ho avuto lo stesso problema come te, e penso che sono riuscito a trovare una soluzione più semplice. Hai solo bisogno di lasciare l’originale menu principale in MainMenu.xib – non verrà visualizzato, ma tutte le azioni saranno trattati correttamente. Il trucco è che deve essere l’originale, se devi solo trascinare una nuova NSMenu dalla libreria, l’app non riconosce come Menu Principale e non ho idea di come marchio e come tale (se si deseleziona la casella LSUIElement, vedrai che non è visibile nella parte superiore, se non è l’originale). Se hai già eliminato, è possibile creare una nuova applicazione di esempio e trascinare un menu dal suo PENNINO, che lavora troppo.

    • Questo ha funzionato per me nel 2017. Ho creato un nuovo xib dal “Menu Principale” Xcode modello – non ha bisogno di una nuova app.
    • Grazie! Questo è un semplice e facile soluzione.
  4. 10

    Ho migliorato di Adrian soluzione a lavorare quando il Caps Lock è così:

    - (void)sendEvent:(NSEvent *)event
    {
        if (event.type == NSKeyDown)
        {
            NSString *inputKey = [event.charactersIgnoringModifiers lowercaseString];
            if ((event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == NSCommandKeyMask ||
                (event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSAlphaShiftKeyMask))
            {
                if ([inputKey isEqualToString:@"x"])
                {
                    if ([self sendAction:@selector(cut:) to:nil from:self])
                        return;
                }
                else if ([inputKey isEqualToString:@"c"])
                {
                    if ([self sendAction:@selector(copy:) to:nil from:self])
                        return;
                }
                else if ([inputKey isEqualToString:@"v"])
                {
                    if ([self sendAction:@selector(paste:) to:nil from:self])
                        return;
                }
                else if ([inputKey isEqualToString:@"z"])
                {
                    if ([self sendAction:NSSelectorFromString(@"undo:") to:nil from:self])
                        return;
                }
                else if ([inputKey isEqualToString:@"a"])
                {
                    if ([self sendAction:@selector(selectAll:) to:nil from:self])
                        return;
                }
            }
            else if ((event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSShiftKeyMask) ||
                     (event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSShiftKeyMask | NSAlphaShiftKeyMask))
            {
                if ([inputKey isEqualToString:@"z"])
                {
                    if ([self sendAction:NSSelectorFromString(@"redo:") to:nil from:self])
                        return;
                }
            }
        }
        [super sendEvent:event];
    }
  5. 8

    Thomas Kilian soluzione swift 3.

    private let commandKey = NSEventModifierFlags.command.rawValue
    private let commandShiftKey = NSEventModifierFlags.command.rawValue | NSEventModifierFlags.shift.rawValue
    override func performKeyEquivalent(with event: NSEvent) -> Bool {
      if event.type == NSEventType.keyDown {
        if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
        switch event.charactersIgnoringModifiers! {
        case "x":
          if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
        case "c":
          if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
        case "v":
          if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
        case "z":
          if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
        case "a":
          if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
        default:
          break
        }
      }
      else if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
        if event.charactersIgnoringModifiers == "Z" {
          if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
        }
      }
    }
    return super.performKeyEquivalent(with: event)
    }
    • Poche cose sono cambiate per swift 4. Ma basta fare clic su fix per risolvere. ✌️
  6. 5

    Swift 4.2 per Thomas Kilian soluzione

    class MTextField: NSSecureTextField {
    
        private let commandKey = NSEvent.ModifierFlags.command.rawValue
        private let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue
    
        override func performKeyEquivalent(with event: NSEvent) -> Bool {
            if event.type == NSEvent.EventType.keyDown {
                if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
                    switch event.charactersIgnoringModifiers! {
                    case "x":
                        if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
                    case "c":
                        if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
                    case "v":
                        if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
                    case "z":
                        if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
                    case "a":
                        if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
                    default:
                        break
                    }
                }
                else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
                    if event.charactersIgnoringModifiers == "Z" {
                        if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
                    }
                }
            }
            return super.performKeyEquivalent(with: event)
        }
    
    }
  7. 4

    Qui di seguito un breve passo-passo guida per swift, basato sulla eccellente risposte da @Adrian, Travis B e Thomas Kilian.

    L’obiettivo sarà quello di creare una sottoclasse del NSApplication, invece di NSTextField. Una volta creata questa classe, il link è nella tua “Classe principale” impostazione di Informazioni.plist, come dichiarato da Adriano. Contrariamente a Objective-C, ragazzi, abbiamo swiftlers dovrà aggiungere un ulteriore prefisso per il principalClass di configurazione. Così, perché il mio Progetto si chiama “Pippo”, vado per impostare “Classe Principale” a “Pippo.MyApplication”. Si otterrà un “Classe MyApplication non trovato” errore di runtime altrimenti.

    Il contenuto di MyApplication come segue (copiato e adattato da tutte le risposte date finora)

    import Cocoa
    
    class MyApplication: NSApplication {
        override func sendEvent(event: NSEvent) {
            if event.type == NSEventType.KeyDown {
                if (event.modifierFlags & NSEventModifierFlags.DeviceIndependentModifierFlagsMask == NSEventModifierFlags.CommandKeyMask) {
                    switch event.charactersIgnoringModifiers!.lowercaseString {
                    case "x":
                        if NSApp.sendAction(Selector("cut:"), to:nil, from:self) { return }
                    case "c":
                        if NSApp.sendAction(Selector("copy:"), to:nil, from:self) { return }
                    case "v":
                        if NSApp.sendAction(Selector("paste:"), to:nil, from:self) { return }
                    case "z":
                        if NSApp.sendAction(Selector("undo:"), to:nil, from:self) { return }
                    case "a":
                        if NSApp.sendAction(Selector("selectAll:"), to:nil, from:self) { return }
                    default:
                        break
                    }
                }
                else if (event.modifierFlags & NSEventModifierFlags.DeviceIndependentModifierFlagsMask == (NSEventModifierFlags.CommandKeyMask | NSEventModifierFlags.ShiftKeyMask)) {
                    if event.charactersIgnoringModifiers == "Z" {
                        if NSApp.sendAction(Selector("redo:"), to:nil, from:self) { return }
                    }
                }
            }
            return super.sendEvent(event)
        }
    
    }
  8. 3

    Mi spiega cosa ha funzionato per me in XCode 8 /Swift 3.

    Ho creato MyApplication.swift all’interno della mia cartella di progetto MyApp:

    import Foundation
    import Cocoa
    
    class MyApplication: NSApplication {
        override func sendEvent(_ event: NSEvent) {
            if event.type == NSEventType.keyDown {
    
                if (event.modifierFlags.contains(NSEventModifierFlags.command)) {
                    switch event.charactersIgnoringModifiers!.lowercased() {
                    case "x":
                        if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return }
                    case "c":
                        if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return }
                    case "v":
                        if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return }
                    case "a":
                        if NSApp.sendAction(#selector(NSText.selectAll(_:)), to:nil, from:self) { return }
                    default:
                        break
                    }
                }
            }
            return super.sendEvent(event)
        }
    
    }

    Quindi modificare il Info.plist Principal class per MyApp.MyApplication. Creazione ed esecuzione di confermare che i miei campi di testo e il testo di vista dispone di supporto per Cmd + X, Cmd + C, Cmd + V e Cmd + A.

    • Questa sentenza è molto chiara e semplice. Facilmente adattate e lavoro su Swift 3
    • buona soluzione ! se avete problemi con il principale classe, provare questo post: stackoverflow.com/a/27144383/6662165
  9. 3

    Non c’è bisogno di aggiungere una nuova classe, estensione o davvero qualsiasi tipo di codice.

    1. Basta aggiungere una nuova voce di menu in uno dei menu e il nome loro “Copia”, “Taglia” e “Incolla”.
    2. Aggiungere il corretto tasti di scelta rapida per ogni elemento.
    3. Controllo+trascinare il collegamento ai metodi corrispondenti elencati in primo responder.

    Il bonus qui è che gli elementi non sono nascosti dagli utenti, e questo richiede meno tempo che la creazione di una nuova classe a e la riassegnazione di tutti i campi di testo a.

  10. 3

    Xcode10/Swift 4.2 soluzione:

    import Cocoa
    
    extension NSTextView {
    override open func performKeyEquivalent(with event: NSEvent) -> Bool {
        let commandKey = NSEvent.ModifierFlags.command.rawValue
        let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue
        if event.type == NSEvent.EventType.keyDown {
            if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
                switch event.charactersIgnoringModifiers! {
                case "x":
                    if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
                case "c":
                    if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
                case "v":
                    if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
                case "z":
                    if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
                case "a":
                    if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
                default:
                    break
                }
            } else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
                if event.charactersIgnoringModifiers == "Z" {
                    if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
                }
            }
        }
        return super.performKeyEquivalent(with: event)
    }
    }
    • opere bello, grazie ! 🙂
  11. 0

    Solo circa 1 ora fa mi sono imbattuto su lo stesso problema.
    Non è necessario il codice di nulla. Ho potuto fare questo in Interface Builder:

    • Creare un menu (ad es. “Modifica”) che contiene il Taglia /Copia /Incolla voci di menu
    • Aggiungere il KeyEquivalent per il tasto CMD per il menu “Modifica” (non so se questo è davvero bisogno, ho semplicemente copiato la struttura di un altro progetto)
    • Aggiungere il KeyEquivalents a queste voci di menu (CMD + X e così via)
    • Link il FirstResponder‘s cut:, copy: e paste: funzioni corrispondenti voci di menu

    Che ha funzionato per me.
    Purtroppo questo (default) comportamento non sembra funzionare quando si nasconde il menu “Modifica” (appena provato).

  12. 0

    Ecco Travis risposta come C# per l’uso con Xamarin.Mac:

        public override bool PerformKeyEquivalent (AppKit.NSEvent e)
        {
            if (e.Type == NSEventType.KeyDown) {
                var inputKey = e.CharactersIgnoringModifiers.ToLower ();
                if (   (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == NSEventModifierMask.CommandKeyMask
                    || (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == (NSEventModifierMask.CommandKeyMask | NSEventModifierMask.AlphaShiftKeyMask)) {
                    switch (inputKey) {
                    case "x":
                        NSApplication.SharedApplication.SendAction (new Selector ("cut:"), null, this);
                        return true;
                    case "c":
                        NSApplication.SharedApplication.SendAction (new Selector ("copy:"), null, this);
                        return true;
                    case "v":
                        NSApplication.SharedApplication.SendAction (new Selector ("paste:"), null, this);
                        return true;
                    case "z":
                        NSApplication.SharedApplication.SendAction (new Selector ("undo:"), null, this);
                        return true;
                    case "a":
                        NSApplication.SharedApplication.SendAction (new Selector ("selectAll:"), null, this);
                        return true;
                    }
                } else if (   (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == (NSEventModifierMask.CommandKeyMask | NSEventModifierMask.ShiftKeyMask)
                           || (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == (NSEventModifierMask.CommandKeyMask | NSEventModifierMask.ShiftKeyMask | NSEventModifierMask.AlphaShiftKeyMask)) {
                    switch (inputKey) {
                    case "z":
                        NSApplication.SharedApplication.SendAction (new Selector ("redo:"), null, this);
                        return true;
                    }
                }
            }
            return base.PerformKeyEquivalent(e);
        }
  13. 0

    Base Thomas Kilian‘s risposta, si può effettivamente creare un’estensione per NSTextField

    let commandKey = NSEvent.ModifierFlags.command.rawValue
    let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue
    
    extension NSTextField {
        func performEditingKeyEquivalent(with event: NSEvent) -> Bool {
            guard event.type == NSEvent.EventType.keyDown else { return false }
    
            if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
                if let character = event.charactersIgnoringModifiers {
                    switch character {
                    case "x":
                        if NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self) { return true }
                    case "c":
                        if NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self) { return true }
                    case "v":
                        if NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self) { return true }
                    case "z":
                        if NSApp.sendAction(Selector(("undo:")), to: nil, from: self) { return true }
                    case "a":
                        if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self) { return true }
                    default:
                        break
                    }
                }
            } else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
                if event.charactersIgnoringModifiers == "Z" {
                    if NSApp.sendAction(Selector(("redo:")), to: nil, from: self) { return true }
                }
            }
    
            return false
        }
    }

    In followingg esempio, si può effettivamente sostituire NSTextField con qualsiasi NSTextField ereditando le classi (e.g NSSearchField, NSSecureTextField) per avere nuove funzionalità

    class SearchField: NSTextField {
        override func performKeyEquivalent(with event: NSEvent) -> Bool {
            if performEditingKeyEquivalent(with: event) {
                return true
            }
    
            return super.performEditingKeyEquivalent(with: event)
        }
    }
  14. 0

    Grazie per questa soluzione! Mi ha aiutato molto, così ho deciso di contribuire con un po ‘ di codice nella speranza che aiuta qualcun altro. La soluzione proposta sopra ha funzionato perfettamente dopo che ho convertito a Swift 4.2. Poi ho riscritto il codice un po’. Penso che questo sia un po ‘ più pulito. Questo è Swift 4.2 compatibili:

    //NSEventExtensions.swift
    
    import AppKit
    
    extension NSEvent {
        func containsKeyModifierFlags(_ flags: NSEvent.ModifierFlags) -> Bool {
            switch modifierFlags.intersection(.deviceIndependentFlagsMask) {
            case [flags]: return true
            default: return false
            }
        }
    }
    
    //SearchFiled.swift
    
    import AppKit
    import Carbon
    
    final class SearchField: NSSearchField {
        override func performKeyEquivalent(with event: NSEvent) -> Bool {
            switch event.type {
            case .keyDown: return performKeyDownEquivalent(with: event)
            default: return super.performKeyEquivalent(with: event)
            }
        }
    
        //MARK: - private
    
        private func performKeyDownEquivalent(with event: NSEvent) -> Bool {
            if event.containsKeyModifierFlags(.command) {
                switch Int(event.keyCode) {
                case kVK_ANSI_X: return NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self)
                case kVK_ANSI_C: return NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self)
                case kVK_ANSI_V: return NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self)
                case kVK_ANSI_Z: return NSApp.sendAction(Selector(("undo:")), to: nil, from: self)
                case kVK_ANSI_A: return NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self)
                default: break
                }
            } else if event.containsKeyModifierFlags([.command, .shift]) {
                switch Int(event.keyCode) {
                case kVK_ANSI_Z: return NSApp.sendAction(Selector(("redo:")), to: nil, from: self)
                default: break
                }
            }
            return false
        }
    }
  15. -1

    Adrian soluzione è buona, ma meglio credo per utilizzare un’istruzione switch piuttosto che tutti coloro confronti di stringa, ad esempio:

        uint const modifierCode = (theEvent.modifierFlags & NSDeviceIndependentModifierFlagsMask);
        BOOL usingModifiers = ( modifierCode != 0 );
        //BOOL const usingShiftKey = ((theEvent.modifierFlags & NSShiftKeyMask) != 0);
        //BOOL const usingCommandKey = ((theEvent.modifierFlags & NSCommandKeyMask) != 0);
        NSString * ch = [theEvent charactersIgnoringModifiers];
        if ( ( usingModifiers ) && ( ch.length == 1 ) ) switch ( [ch characterAtIndex:0] )
        {
            case 'x':
                if ( modifierCode == NSCommandKeyMask ) [m cut]; //<-- m = model
                break;
            case 'c':
                if ( modifierCode == NSCommandKeyMask ) [m copy];
                break;
            case 'v':
                if ( modifierCode == NSCommandKeyMask ) [m paste];
                break;
            case 'z':
                if ( modifierCode == NSCommandKeyMask ) [m undo];
                break;
            case 'Z':
                if ( modifierCode == ( NSCommandKeyMask | NSShiftKeyMask ) ) [m redo];
                break;
            default: //etc.
                break;
        }
        else switch ( theEvent.keyCode ) //<-- for independent keycodes!
        {
            case kVK_Home:
                [m moveToBeginningOfDocument:nil];
                break;
            case kVK_End: //etc!

Lascia un commento