2

我有一个NSPanel奇怪的行为问题,并创建了一个示例应用程序来演示这种行为。

该应用程序是从 Xcode 4 的模板生成的,只需创建一个面板,然后根据按钮按下打开和关闭它:

在此处输入图像描述

我观察到的奇怪行为:

  1. 在 Lion 下,第一次打开面板后,面板跟随主窗口,这是正确的行为。但是,在关闭它然后重新打开它之后,它不再跟随主窗口。
  2. 在 Snow Leopard 下,关闭面板时,主窗口也会关闭!

编辑:为了清楚起见;我期望的行为是让面板在主窗口移动时跟随主窗口;并在面板关闭并随后重新打开后实现这一点。此外,我希望面板和主窗口在 Snow Leopard 和 Lion 下的行为方式相同。

代码的重要部分在这里:

@implementation MyAppDelegate

- (void)dealloc
{
    [_panel release];
    [super dealloc];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    _panel = [[NSPanel alloc]
             initWithContentRect:NSMakeRect(400, 400, 200, 100)
             styleMask:NSUtilityWindowMask|NSClosableWindowMask|NSTitledWindowMask
             backing:NSBackingStoreBuffered
             defer:YES];
    [_panel setTitle:@"A Panel"];
}

- (IBAction)openPanel:(id)sender
{
    [_panel setParentWindow:[self window]];
    [_panel makeKeyAndOrderFront:sender];
}

- (IBAction)closePanel:(id)sender
{
    [_panel orderOut:sender];
}

@end

注意:我在方法中添加了不必要的setParentWindow调用,openPanel以断言每次打开面板时都会重置父窗口;然而,它没有任何区别。

有人可以解释我做错了什么吗?

编辑:对于实现文件中的缺失存在一些混淆@synthesize window = _window,但我刚刚打开了另一个项目示例,该示例是我为测试内存泄漏行为而创建的,但它也不存在。我使用的是 Xcode 4.4,所以这可能是一个错误,但我认为项目模板没有改变。

4

2 回答 2

3

您不应该从孩子设置父子关系,而是从父母那里设置。setParentWindow:文档说:

当该方法被子类的实现覆盖时,应从子类调用此方法。不应以其他方式调用它。

相反,使用addChildWindow:ordered:,如下所示:

- (IBAction)openPanel:(id)sender
{
    [[self window] addChildWindow:_panel ordered:NSWindowAbove];
    //[_panel setParentWindow:[self window]];
    [_panel makeKeyAndOrderFront:sender];
}

我没有在 Snow Leopard 下对此进行测试,但它修复了我在 Lion 上运行时的行为。

Rob Keniger 在下面指出,在 Snow Leopard 上,您也应该[[self window] removeChildWindow:_panel]在订购面板之前进行操作。(我认为这对 Lion 也是一个好主意。)

于 2012-04-29T22:12:23.813 回答
0

我对你的问题有点困惑。我下载并检查了你的项目。首先,不知何故你错过了应用程序主窗口的@synthesize 命令。你说你使用了模板,但不知何故它不见了。由于 AppDelegate 头文件有一个窗口的@property,因此您需要在它的实现文件中使用@synthesize 命令。我不确定您是如何在项目中丢失该行的,但将其添加到 @implementation 行之后...

@synthesize window = _window;

第二,为什么要说以下内容?

在 Lion 下,第一次打开面板后,面板跟随主窗口四处走动,这是正确的行为。

你说的没有道理。创建面板时,您使用“ initWithContentRect:NSMakeRect(400, 400, 200, 100) ”。请注意,您在 (400, 400) 位置创建它,大小为 (200, 100)。所以第一次打开时,它会在屏幕位置(400、400)打开。它与主窗口的位置无关。

无论如何,在添加 @synthesize 部分后,我可以编译并运行应用程序而没有错误。对我来说,它在 10.7 中按预期工作。

于 2012-04-29T21:58:20.140 回答