2011-08-30 197 views
5

我正在使用OS X的应用程序,在该应用程序中使用自定义窗口来绘制图像作为背景(包括标题栏)。我一直在修改this code以绘制窗口,然后调用[NSWindow standardWindowButton:forStyleMask:]以获得标准关闭,最小化和最大化按钮。覆盖NSWindow关闭按钮

问题是我的应用程序使用NSPopovers,当弹出窗口打开时关闭或最小化应用程序时,它将关闭弹出窗口或显示弹出窗口的动画而不是关闭应用程序。有没有方法可以覆盖NSWindow中的默认关闭/最小化行为,以便我可以先关闭任何打开的弹出窗口?

谢谢,如果这是一个明显的问题,很抱歉 - 这是我第一次使用OS X SDK,所以我没有太多的经验。

编辑:我张贴这种几个小时后,我想我有一个显而易见的解决方案 - 使用NSWindowDelegate方法“windowWillClose:”和“windowWillMiniaturize:”和罢免popovers那里。但是,由于关闭/最小化按钮正在关闭弹出窗口,所以如果弹出窗口打开,这些委托方法将不会被调用。这让我回到第1步,但希望知道这种行为将有助于人们找出问题所在。

NSPopovers还存在另一个问题,我不知道它是否连接,所以我想我会在这里添加它以防万一有一个共同的原因。有时,当我试图解散popover时,我会得到这个错误(对于上下文,我按下一个NSButton调用一个检查popover是否存在的函数,如果存在,则关闭它):

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 
) 

回答

3

解决方案结果相当简单。

当我创建对NSWindow按钮,我改变了按钮的动作和目标:

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

然后在NSWindowController子类中,我实现的方法,包括:

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

对于某些原因,当窗口重新打开或未被最小化时,NSPopovers总是重新出现;因为我实际上在我的应用程序中需要这种行为,所以这不是问题,但是如果您使用此解决方案,请记住这一点。如果您没有任何子窗口,那么您可以遍历self.window.childWindows,因为NSPopovers被视为子窗口。如果您想要另外处理其他子窗口,则可以向NSWindow子类添加一个数组,以监视所有弹出窗口,然后遍历该窗口。

+0

但是...怎么样的堆栈跟踪?!我需要知道。 –

+0

@ Big-OClaire不幸的是,这个问题已经接近6岁了,我实际上无法再访问源代码,所以我不能帮你。抱歉! – Aaron