我是MacRuby和Cocoa的完整n00b,所以在回答时请记住这一点 - 我需要大量细节和解释。 :)
我已经设置了一个简单的项目,里面有2个窗口,这两个窗口都是用Interface Builder构建的。第一个窗口是使用表视图的简单帐户列表。它下面有一个“+”按钮。当我点击+按钮时,我想显示一个“添加新帐户”窗口。
我还有一个AccountsController < NSWindowController
和一个AddNewAccountController < NSWindowController
类,设置为这些窗口的代理,使用相应的按钮单击方法连接,以及引用以引用所需的窗口。
当我点击“帐户”窗口中的“+”按钮时,我会触发此代码:
@add_account.center
@add_account.display
@add_account.makeKeyAndOrderFront(nil)
@add_account.orderFrontRegardless
第一次单击+按钮时这很有用。一切都显示出来,我能够输入我的数据并将其绑定到我的模型。但是,当我关闭添加新帐户表单时,情况开始变坏。
如果我将添加新帐户窗口设置为在关闭时释放,那么第二次单击+按钮时,窗口仍会弹出,但它已冻结。我无法点击任何按钮,输入任何数据,甚至关闭表格。我认为这是因为表单的代码已经发布,所以没有消息循环处理表单......但我不完全确定这一点。
如果我将添加新帐户窗口设置为在关闭时不释放,则第二次单击+按钮,窗口显示正常并且可用 - 但它仍然具有我之前输入的所有数据。 ..它仍然绑定到我以前的Account类实例。
我做错了什么?当我点击“帐户”表单上的+按钮时,创建“添加新帐户”表单的新实例,创建新帐户模型,将该模型绑定到表单并显示表单的正确方法是什么?......这一切都在OSX 10.6.6,64bit上进行,使用XCode 3.2.4
答案 0 :(得分:1)
问题是它不会每次都创建窗口。关闭时释放是一个令人烦恼的选项,通常仅在窗口关闭时知道窗口控制器也被释放时使用。 (注意我从来没有使用过MacRuby所以我会在Obj-C中给出代码,因为我知道它是正确的,希望你可以转换它。我将假设GC应该与MacRuby一样开启。)< / p>
现在有两种方法可以做到这一点。我不完全确定你的NIB /类是如何设置的,因为它可能是两种方式之一。
-
解决问题的第一种方法是使用你用来引用表单元素的出口,当你再次显示窗口时将它们删空,例如[myTextField setStringValue:@“”]。如果你正在使用cocoa绑定,那么它有点棘手,但基本上你必须确保绑定的对象被消隐。如果你是Cocoa的新手,我建议不要使用绑定。
-
第二种方法是使AddNewAccountController类成为NSWindowController的子类。当您按下+按钮时,您将创建一个新实例并显示它(记得将其存储在ivar中)。最好的方法就是这样:
if (!addAccountController) {
addAccountController = [[AddNewAccountController alloc] initWithWindowNibName:@"AddNewAccountController"];
[[addAccountController window] setDelegate:self];
}
[addAccountController showWindow:self];
如果窗口已经可见,这可以防止生成新实例。然后,您需要实现委托:
- (void)windowWillClose:(NSNotification *)notification {
//If you don't create the account in the AddNewAccountController then do it here
addAccountController = nil;
}
显然,您需要将窗口移动到名为“AddNewAccountController”的单独NIB。在这个NIB中,确保将File的Owner的类设置为AddNewAccountController,然后将File的Owner的窗口连接到窗口。
设置完所有这些后,每次都会有一个新的控制器/窗口。它还具有将笔尖和控制器分成更集中的单元的好处。
-
最后一件事。虽然可以在窗口中执行此类操作,但您最终可能希望通过工作表执行此操作,因为这样可以防止添加帐户窗口隐藏在其他窗口后面的可能性。