5

我正在开发一个适用于 OS X 的应用程序,在该应用程序中,我使用了一个自定义窗口,该窗口将图像绘制为背景,包括标题栏。我一直在修改这段代码来绘制窗口,然后调用 [NSWindow standardWindowButton:forStyleMask:] 来获得标准的关闭、最小化和最大化按钮。

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

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

编辑:在我发布这篇文章几个小时后,我认为我有一个明显的解决方案——使用 NSWindowDelegate 方法“windowWillClose:”和“windowWillMiniaturize:”并消除那里的弹出框。但是,似乎由于关闭/最小化按钮正在关闭弹出框,如果弹出框打开,则不会调用这些委托方法。这让我回到了第 1 步,但希望知道这种行为会帮助某人找出问题所在。

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

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

1 回答 1

4

结果证明解决方案相当简单。

当我在 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 子类添加一个数组,该数组监视所有弹出窗口并对其进行迭代。

于 2011-09-01T21:50:20.653 回答