2011-08-30 9 views
5

Estoy trabajando en una aplicación para OS X donde utilizo una ventana personalizada que dibuja una imagen como fondo, incluida la barra de título. He estado modificando this code para dibujar la ventana, y luego llamando [NSWindow standardWindowButton: forStyleMask:] para obtener los botones estándar de cerrar, minimizar y maximizar.Invalidar NSWindow botón de cierre

El problema es que mi aplicación usa NSPopovers, y cuando cierro o minimizo la aplicación mientras está abierto un popover, cerrará el popover o mostrará una animación de la minimización de popover en lugar de cerrar la aplicación. ¿Hay alguna manera de anular el comportamiento predeterminado de cerrar/minimizar en NSWindow para que pueda descartar cualquier popover abierto primero?

Gracias, y lo siento si esta es una pregunta obvia: esta es la primera vez que trabajo con el SDK de OS X, así que no tengo mucha experiencia.

EDIT: Unas pocas horas después de que envió este pensé que tenía una solución obvia - utilizar el NSWindowDelegate métodos "windowWillClose:" y "windowWillMiniaturize:" y separar a los panecillos allí. Sin embargo, parece que debido a que los botones de cerrar/minimizar están cerrando el popover, si un popover está abierto, estos métodos delegados no se invocarán. Esto me lleva de vuelta al paso 1, pero con suerte conocer el comportamiento ayudará a alguien a resolver el problema.

También hay otro problema con NSPopovers y no sé si está conectado o no, así que pensé que lo agregaría aquí en caso de que hubiera una causa común. A veces, cuando intento descartar un popover, obtendré este error (para el contexto, estoy presionando un NSButton que llama a una función que comprueba la existencia del popover, y si existe, lo cierra):

2011-08-30 11:24:08.949 Playground[11194:707] *** Assertion failure in +[NSView _findFirstKeyViewInDirection:forKeyLoopGroupingView:], /SourceCache/AppKit/AppKit-1138/AppKit.subproj/NSView.m:11026 
2011-08-30 11:24:08.950 Playground[11194:707] this method is supposed to only be invoked on top level items 
2011-08-30 11:24:08.958 Playground[11194:707] (
    0 CoreFoundation      0x00007fff873d4986 __exceptionPreprocess + 198 
    1 libobjc.A.dylib      0x00007fff87ac6d5e objc_exception_throw + 43 
    2 CoreFoundation      0x00007fff873d47ba +[NSException raise:format:arguments:] + 106 
    3 Foundation       0x00007fff8950314f -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 169 
    4 AppKit        0x00007fff88211064 +[NSView _findFirstKeyViewInDirection:forKeyLoopGroupingView:] + 137 
    5 AppKit        0x00007fff87d1f546 _replacementKeyViewAlongKeyViewPath + 565 
    6 AppKit        0x00007fff87d1f2ff -[NSView nextValidKeyView] + 179 
    7 AppKit        0x00007fff87d1f199 -[NSWindow _selectFirstKeyView] + 714 
    8 AppKit        0x00007fff882361cf _NSWindowRecursiveFindFirstResponder + 164 
    9 AppKit        0x00007fff882395c8 _NSWindowExchange + 79 
    10 AppKit        0x00007fff883a7e3a -[_NSWindowTransformAnimation startAnimation] + 426 
    11 AppKit        0x00007fff87c98bb2 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 592 
    12 AppKit        0x00007fff87c9890f -[NSWindow orderWindow:relativeTo:] + 154 
    13 AppKit        0x00007fff883dfaf0 _NSPopoverCloseAndAnimate + 948 
    14 Playground       0x00000001000078a4 -[MainWindowController dismissPopover:] + 100 
    15 Playgorund       0x0000000100007012 -[MainWindowController requestWasClicked:] + 98 
    16 CoreFoundation      0x00007fff873c411d -[NSObject performSelector:withObject:] + 61 
    17 AppKit        0x00007fff87ca2852 -[NSApplication sendAction:to:from:] + 139 
    18 AppKit        0x00007fff87ca2784 -[NSControl sendAction:to:] + 88 
    19 AppKit        0x00007fff87ca26af -[NSCell _sendActionFrom:] + 137 
    20 AppKit        0x00007fff87ca1b7a -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2014 
    21 AppKit        0x00007fff87d2157c -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 489 
    22 AppKit        0x00007fff87ca0786 -[NSControl mouseDown:] + 786 
    23 AppKit        0x00007fff87c6b66e -[NSWindow sendEvent:] + 6280 
    24 AppKit        0x00007fff87c03f19 -[NSApplication sendEvent:] + 5665 
    25 AppKit        0x00007fff87b9a42b -[NSApplication run] + 548 
    26 AppKit        0x00007fff87e1852a NSApplicationMain + 867 
    27 Playground       0x0000000100001c52 main + 34 
    28 Playground       0x0000000100001c24 start + 52 
    29 ???         0x0000000000000001 0x0 + 1 
) 

Respuesta

3

La solución resultó ser bastante simple.

Cuando creé el botón de la NSWindow, me cambió la acción y el destino del botón:

[closeButton setTarget:self.delegate]; // alternatively you can make it self.windowController 
[closeButton setAction:@selector(closeThisWindow:)]; 

Y luego, en la subclase NSWindowController, que implementa el método:

-(void)closeThisWindow { 
    [self close]; // for the minimize button you'll call [self.window miniaturize] 
} 

Para alguna razón, los NSPopovers siempre reaparecen cuando la ventana se reabre o no se minimiza; ya que realmente quiero este comportamiento en mi aplicación, no es un problema, pero es algo a tener en cuenta si usa esta solución. Si no tiene ventanas secundarias, puede iterar por self.window.childWindows porque las NSPopovers se consideran ventanas secundarias. Si tiene otras ventanas secundarias que desea manejar por separado, puede agregar una matriz a la subclase NSWindow que supervisa todos sus elementos emergentes y simplemente iterar a través de eso.

+0

Pero ... ¿qué pasa con el rastro de la pila ?! NECESITO SABER. –

+0

@ Big-OClaire Lamentablemente, esta pregunta se acerca a los 6 años y ya no tengo acceso al código fuente, así que no puedo ayudarlo. ¡Lo siento! – Aaron