2011-08-30 13 views
5

Sto lavorando a un'applicazione per OS X in cui utilizzo una finestra personalizzata che disegna un'immagine come sfondo, inclusa la barra del titolo. Ho modificato this code per disegnare la finestra e quindi chiamando [NSWindow standardWindowButton: forStyleMask:] per ottenere i pulsanti standard di chiusura, riduzione a icona e ingrandimento.Override NSWindow close button

Il problema è che la mia applicazione utilizza NSPopovers e quando chiudo o minimizzo l'applicazione mentre è aperto un popover, chiuderà il popover o mostrerà un'animazione del popover che riduce a icona invece di chiudere l'applicazione. C'è un modo per sovrascrivere il comportamento di chiusura/riduzione predefinito in una NSWindow in modo da poter eliminare prima tutti i popover aperti?

Grazie, e scusa se questa è una domanda ovvia - questa è la prima volta che lavoro con OS X SDK, quindi non ho molta esperienza.

EDIT: Poche ore dopo che ho postato questo pensavo di avere una soluzione ovvia - utilizzare la NSWindowDelegate metodi "windowWillClose:" e "windowWillMiniaturize:" e respingere i popovers lì. Tuttavia, sembra che dal momento che i pulsanti close/minimize chiudano il popover, che se un popover è aperto, questi metodi delegati non verranno richiamati. Questo mi riporta al punto 1, ma spero che la conoscenza del comportamento possa aiutare qualcuno a capire il problema.

C'è anche un altro problema con NSPopovers e non so se è collegato o meno, quindi ho pensato di aggiungerlo qui nel caso in cui ci fosse una causa comune. A volte, quando provo a eliminare un popover, visualizzerò questo errore (per il contesto, premo un NSButton che chiama una funzione che controlla l'esistenza del popover e, se esiste, lo chiude):

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 
) 

risposta

3

La soluzione si è rivelata abbastanza semplice.

Quando ho creato il pulsante sul NSWindow, ho cambiato l'azione e di destinazione del pulsante:

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

E poi nella sottoclasse NSWindowController, ho implementato il metodo:

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

Per qualche ragione, gli NSPopovers riappaiono sempre quando la finestra viene riaperta o non viene minimizzata; dal momento che in realtà desidero questo comportamento nella mia applicazione, non è un problema, ma è qualcosa da tenere a mente se si utilizza questa soluzione. Se non si dispone di finestre secondarie, è possibile ripetere l'iterazione tramite self.window.childWindows poiché NSPopovers sono considerate finestre figlio. Se si dispone di altre finestre secondarie che si desidera gestire separatamente, è possibile aggiungere una matrice alla sottoclasse NSWindow che monitora tutti i popover e esegue semplicemente un'iterazione.

+0

Ma ... e la traccia dello stack ?! HO BISOGNO DI SAPERE. –

+0

@ Big-OClaire Sfortunatamente, questa domanda si avvicina ai 6 anni e in realtà non ho più accesso al codice sorgente, quindi non posso aiutarti. Scusate! – Aaron