我有一个使用带有主窗口的垃圾收集构建的Cocoa应用程序。该窗口提供了一个按钮,当按下该按钮时触发窗口控制器上的操作,如下所示:
- (IBAction) buttonClick:(id)sender {
utilityWindowController = [[UtilityWindowController alloc] initWithWindowNibName:@"Utility"];
[utilityWindowController showWindow:sender];
}
这很好用,除了每次点击按钮时,即使我最后点击的那个窗口仍然显示,也会打开一个新窗口。好的 - 这就是我要求它做的,但我一次只想要一个这个窗口的实例。所以我想要的行为是:
为了试图解决这个问题,我尝试了这个:
- (IBAction) buttonClick:(id)sender {
if (!utilityWindowController) {
utilityWindowController = [[UtilityWindowController alloc] initWithWindowNibName:@"Utility"];
}
[utilityWindowController showWindow:sender];
}
因此效果更好,因为现在我的主窗口会记住我第一次单击按钮时创建的控制器,只显示窗口(如果已有)。但是,它基本上是重用同一个窗口,这会导致另一个问题。
实用程序窗口具有图形显示,并在首次创建时启动计时器。实用程序窗口控制器有一个windowWillClose:方法,当窗口关闭时禁用定时器,因为当用户看不到显示时,继续让定时器触发是没有用的。但是,当用户单击主窗口中的按钮以再次显示实用程序窗口时,窗口显示正常,但计时器不会再次启动。
我似乎无法找到像windowWillShow:我可以用来重启定时器的方法。
另一种方法是,如果上面的代码能够检测到实用程序窗口已关闭并重新创建一个新代码,那么将调用awakeFromNib方法来启动计时器。但是,我不知道如何做到这一点。
第三种方法当然是继续使用上面代码的第二个版本,但是调用一个单独的方法,我将在实用程序窗口控制器中提供,如果尚未运行,它将启动计时器。
处理此类事物的最佳方法是什么?它似乎是一个相当标准的窗口管理的东西,但我还没有在Cocoa中找到正确的方法。
答案 0 :(得分:2)
在订购窗口时没有委托方法或通知。
我会给窗口控制器另一个显示窗口的方法(如果它还没有启动)并启动计时器(如果它还没有运行),并让buttonClick:
只是将该消息发送到窗口控制器。
另一种方法是使用原始代码,在创建窗口控制器后禁用按钮,并在窗口关闭时重新启用按钮(并销毁窗口控制器)。这样做的缺点是它使用户没有简单的方法从第一个窗口返回到第二个窗口(例如,如果他们在屏幕上有很多窗口)。如果您启用该按钮,即使它已经启动,您也可以让它再次对窗口进行排序。这就是为什么我会按照上面的建议去做。
答案 1 :(得分:1)
尝试在其他窗口可见时禁用该按钮,并在windowWillClose方法中重新启用该按钮。然后,您也可以通过buttonClick方法重置计时器,或者在弹出视图的windowWillClose方法中禁用它,以及重置。
[button setEnabled: NO]
答案 2 :(得分:1)
为什么不从awakeFromNib中取出计时器,并创建它以便重复使用它。把它变成一个(@property)。这样您就可以重用它并在需要时使其无效。有趣的是,我刚刚发布了一个做here
的例子