2012-02-05 6 views
5

Realmente me gustaría que mi vista personalizada funcione con -moveLeft:, -deleteForward:, -selectAll:, etc., pero también me gustaría pasar cualquier llave que no me interesara en la cadena de respuesta. En este momento estoy anulando -keyDown: para llamar al [self interpretKeyEvents:[NSArray arrayWithObject:event]];, pero esto parece acaparar todos los eventos clave, incluso aquellos a los que mi vista no responde.Ver interpretKeyEvents: ¿pero pasar los no deseados a la cadena de respuesta?

¿Hay alguna forma de pasar eventos no deseados a lo largo de la cadena, pero todavía responden a -moveLeft:, etc.? ¿O debo implementar todas mis propias acciones en -keyDown: para saber lo que hice y lo que no respondí?

+0

Prueba mi [solución] (http://stackoverflow.com/a/23897022/1067147) – WINSergey

Respuesta

6

Encontré este intento de encontrar una solución a este mismo problema. Nunca encontré nada en línea, pero se me ocurrió algo que parece funcionar bien hasta ahora. Esto es lo que estoy haciendo:

Subclase su NSTextView (o lo que sea que esté usando) y cree una variable de instancia para almacenar temporalmente el evento de desactivación de la tecla. . .

@interface MyTextView : NSTextView { 
    NSEvent* _keyDownEvent; 
} 

@end 

a continuación, definir los métodos de su visión como tal (sacar la basura/liberación retener si está utilizando el recuento de referencias automática):

@implementation MyTextView 

- (id)initWithFrame:(NSRect)frame { 
    if (self = [super initWithFrame:frame]) { 
     _keyDownEvent = nil; 
    } 

    return self; 
} 

- (void)keyDown:(NSEvent*)event { 
    [_keyDownEvent release]; 
    _keyDownEvent = [event retain]; 
    [super keyDown:event]; 
} 

- (void)doCommandBySelector:(SEL)selector { 
    if (_keyDownEvent && selector == @selector(noop:)) { 
     if ([self nextResponder]) { 
      [[self nextResponder] keyDown:[_keyDownEvent autorelease]]; 
     } else { 
      [_keyDownEvent release]; 
     } 
     _keyDownEvent = nil; 
    } else { 
     [super doCommandBySelector:selector]; 
    } 
} 

- (void)dealloc { 
    [_keyDownEvent release]; 

    [super dealloc]; 
} 

@end 

Así es como llegué a este. Cuando no se maneja una tecla, escucha un tono de pitido. Por lo tanto, me puse un punto de interrupción en NSBeep(), y cuando el programa se rompió, escupo a cabo un seguimiento de pila en GDB:

#0 0x00007fff96eb1c2d in NSBeep() 
#1 0x00007fff96e6d739 in -[NSResponder doCommandBySelector:]() 
#2 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#3 0x00007fff96fda826 in -[NSWindow doCommandBySelector:]() 
#4 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#5 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#6 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#7 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#8 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#9 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#10 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#11 0x00007fff96f486ce in -[NSTextView doCommandBySelector:]() 
#12 0x00007fff96da1c93 in -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) interpretEventAsCommand:forClient:]() 
#13 0x00007fff970f5382 in -[NSTextInputContext handleEvent:]() 
#14 0x00007fff96fbfd2a in -[NSView interpretKeyEvents:]() 
#15 0x00007fff96f38a25 in -[NSTextView keyDown:]() 
#16 0x0000000100012889 in -[MyTextView keyDown:] (self=0x1004763a0, _cmd=0x7fff972b0234, event=0x100197320) at /path/MyTextView.m:24 
#17 0x00007fff96a16b44 in -[NSWindow sendEvent:]() 
#18 0x00007fff969af16d in -[NSApplication sendEvent:]() 
#19 0x00007fff969451f2 in -[NSApplication run]() 
#20 0x00007fff96bc3b88 in NSApplicationMain() 
#21 0x00000001000015e2 in main (argc=3, argv=0x7fff5fbff8f0) at /path/main.m:12 

Lo que sucede es lo siguiente: Cuando el evento pulsada la tecla no se utiliza para la entrada de texto , un comando "noop" se envía a la cadena de respuesta. Por defecto, esto activa un pitido cuando se cae de la cadena de respuesta. En mi solución, la subclase NSTextView capta el comando noop y en su lugar arroja el evento KeyDown original por la cadena de respuesta. Entonces su NSWindow u otras vistas obtendrán los eventos KeyDown no utilizados como normales.

3

Ésta es mi aplicación rápida de respuesta de @ daxnitro, y parece que funciona:

import Cocoa 

class EditorTextView: NSTextView { 

    private var keyDownEvent: NSEvent? 

    required init?(coder aCoder: NSCoder) { 
     super.init(coder: aCoder) 
    } 

    override init() { 
     super.init() 
    } 

    override init(frame frameRect: NSRect, textContainer aTextContainer: NSTextContainer!) { 
     super.init(frame: frameRect, textContainer: aTextContainer) 
    } 

    override func keyDown(event: NSEvent) { 
     keyDownEvent = event 
     super.keyDown(event) 
    } 

    override func doCommandBySelector(aSelector: Selector) { 
     if aSelector != NSSelectorFromString("noop:") { 
      super.doCommandBySelector(aSelector) 
     } else if keyDownEvent != nil { 
      self.nextResponder?.keyDown(keyDownEvent!) 
     } 
     keyDownEvent = nil 
    } 

} 
Cuestiones relacionadas