Сочетания клавиш какао в диалоге без меню редактирования

у меня естьLSUIElement приложение, которое отображает элемент состояния меню. Приложение может отображать диалоговое окно, которое содержит текстовое поле.

Если пользователь щелкает правой кнопкой мыши / удерживает нажатой клавишу «Control», в текстовом поле появляется меню, в котором можно вырезать, скопировать, вставить и т. Д. Однако стандартные сочетания клавиш Command-X, Command-C и Command-V не работают в поле. Я предполагаю, что это потому, что мое приложение не предоставляет меню «Правка» с указанными ярлыками.

Я попытался добавить пункт меню «Правка» в меню моего приложения, как предложено вОтправьте код блог, но это не сработало. Можно использовать пункты меню в меню «Правка», но сочетания клавиш по-прежнему не работают.

Я могу представить несколько способов взломать работу с клавиатурой, но есть ли «рекомендуемый» способ заставить это работать?

(Подробнее о приложении см.Menubar Обратный отсчет.)

Связанный вопрос:Копирование / вставка не работает в модальном окне

Ответы на вопрос(15)

    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);
    }

На основеThomas Kilianответ, вы можете создать расширение для 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
    }
}

В следующем примере можно заменитьNSTextField с любым изNSTextField наследующие классы (например,NSSearchField, NSSecureTextField) иметь новый функционал

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

        return super.performEditingKeyEquivalent(with: event)
    }
}

расширение или вообще какой-либо код.

Просто добавьте новые элементы MenuItem в одно из ваших меню и назовите их «Копировать», «Вырезать» и «Вставить».Добавьте правильные сочетания клавиш для каждого элемента.Ctrl + перетащите, чтобы соединить их с соответствующими методами, перечисленными в первом респонденте.

Бонусом здесь является то, что элементы не скрыты от ваших пользователей, и это занимает меньше времени, чем создание нового класса и переназначение ему всех существующих текстовых полей.

основанное на превосходных ответах @Adrian, Travis B и Thomas Kilian.

Целью будет создание подкласса NSApplication вместо NSTextField. После того, как вы создали этот класс, сделайте ссылку на него в настройках «основного класса» Info.plist, как заявлено Адрианом. В отличие от людей Objective-C, мы, swiftlers, должны будем добавить дополнительный префикс к конфигурации PrincipalClass. Итак, поскольку мой проект называется «Foo», я собираюсь установить «Основной класс» в «Foo.MyApplication». В противном случае вы получите сообщение об ошибке «Class MyApplication not found».

Содержимое MyApplication читается следующим образом (скопировано и адаптировано из всех ответов, данных до сих пор)

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)
    }

}
Решение Вопроса

Решение View представлены вКопирование и вставка сочетаний клавиш на CocoaRocket.

В основном это означает создание подкласса NSTextField и переопределениеperformKeyEquivalent:.

Обновить: Сайт CocoaRocket явно исчез. Вот ссылка на Интернет-архив:http://web.archive.org/web/20100126000339/http://www.cocoarocket.com/articles/copypaste.html

редактировать: Код Swift выглядит следующим образом

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)
  }
}

Редактировать: Код Swift 3 выглядит следующим образом

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)
 }
}
 Dave23 мар. 2016 г., 10:24
Решение Swift 2.2 - ответВот.
 Sergey Molyak26 июл. 2017 г., 09:42
Но это не работает с другими языками :( Просто используйтеevent.keyCode вместоevent.charactersIgnoringModifiers

поэтому я решил добавить некоторый код в надежде, что это поможет кому-то еще. Предложенное выше решение отлично работает после того, как я преобразовал его вSwift 4.2, Затем я немного переработал код. Я думаю, что это немного чище. ЭтоSwift 4.2 совместимый:

// 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
    }
}

чтобы оно работало, когда включен Caps Lock:

- (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];
}

Решение Xcode10 / Swift 4.2:

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)
}
}

как и у вас, и я думаю, что мне удалось найти более простое решение. Вам просто нужно оставить оригинальное главное меню в MainMenu.xib - оно не будет отображаться, но все действия будут выполнены правильно. Хитрость заключается в том, что он должен быть оригинальным, если вы просто перетаскиваете новое NSMenu из библиотеки, приложение не распознает его как главное меню, и я понятия не имею, как пометить его как таковой (если вы снимите флажок с LSUIElement, вы увидите, что он не будет отображаться вверху, если он не является оригинальным). Если вы уже удалили его, вы можете создать новое приложение-образец и перетащить меню из его NIB, которое тоже работает.

 Zeus21 авг. 2018 г., 16:12
Спасибо! Это было простое и легкое решение.
 Aaron Frary17 июл. 2017 г., 17:24
Это сработало для меня в 2017 году. Я создал новый xib из шаблона Xcode «Главное меню» - новое приложение не понадобилось.

но лучше, я думаю, использовать оператор switch, а не все эти сравнения строк, например:

    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!

Томас Килиан решение в Свифте 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)
}
 eonist28 авг. 2017 г., 11:27
Несколько изменений в swift 4. Но просто нажмите кнопку «исправить», чтобы решить. ✌

Следующее избавляет от необходимости создавать подкласс NSTextField и помнить об использовании подкласса во всем приложении; это также позволит копировать, вставлять и друзей для других респондентов, которые обрабатывают их, например. NSTextView.

Поместите это в подкласс NSApplication и соответственно измените основной класс в вашем Info.plist.

- (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 {}
 Adrian01 сент. 2011 г., 00:41
Я исправил это, чтобы включить повтор.
 Nate Symer28 мая 2015 г., 20:39
Хотя мне не нравится идея создания подклассов NSApplication,этот код работает хорошо, Мое приложение без XIB и MainMenu, и всякий раз, когда я пытался добавитьNSTextField как подпредставление к окну без полей, ни один из сочетаний клавиш не будет работать (я даже переопределилcanBecomeKeyWindow).
 Scofield Tran25 февр. 2017 г., 18:19
Спасибо Адриану, это работает как чудо, я просто хочу заметить, что мой Xcode выдает 2 предупреждения о том, что селектор (отмена :) и селектор (повтор :)) не распознаются, но на самом деле они работают во время выполнения, просто игнорируйте предупреждения. Я думаю, что мое уведомление может помочь кому-то
 Julian F. Weinert23 авг. 2014 г., 18:09
Кроме того, мне пришлось заменитьNSApplication с моим подклассом вmain.m
 Nikita Rybak04 февр. 2011 г., 17:21
Идеальное решение! Еще одним недостатком оригинала было то, что вам пришлось бы «переопределять» подклассыNSTextField тоже вродеNSSearchField.

кодировать. Я мог бы сделать это в Интерфейсном Разработчике:

Создайте меню (например, «Редактировать»), которое содержит ваши пункты меню Вырезать / Копировать / ВставитьДобавьте KeyEquivalent для клавиши CMD в меню «Правка» (не знаю, действительно ли это необходимо, я просто скопировал структуру из другого проекта)Добавьте KeyEquivalents к этим пунктам меню (CMD + X и т. Д.)СсылкаFirstResponder«scut:, copy: а такжеpaste: функции для ваших соответствующих пунктов меню

Это сработало для меня. К сожалению, это поведение (по умолчанию) не работает, когда вы скрываете меню «Правка» (только что попробовал).

я создалMyApplication.swift внутри моей папки проекта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)
    }

}

Затем изменитеInfo.plist Principal class вMyApp.MyApplication, Создайте и запустите, чтобы проверить, что мои текстовые поля и текстовые представления поддерживаютCmd + X, Cmd + C, Cmd + V а такжеCmd + A.

 laoyur25 апр. 2017 г., 03:57
хорошее решение! если у вас проблемы с основным классом, попробуйте этот пост:stackoverflow.com/a/27144383/6662165
 David Evony24 мар. 2017 г., 17:40
Эта инструкция очень четкая и понятная. Легко адаптируется и работает на Swift 3

Swift 4.2 для решения Томаса Килиана

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)
    }

}

Ваш ответ на вопрос