30

我花了很多时间来消除对 Objective-C 的“ModalForWindow”语言以及如何使用模态会话的困惑。也许以下提示可以节省一些时间:

(如果您不熟悉这个概念:当窗口(通常是面板)运行模式时,它会阻止应用程序的其他部分响应,直到它被关闭。)

“ModalForWindow”在不同的情况下意味着不同的东西。如果您使用 loadNibNamed 来显示由 xib 定义的面板,并且希望它运行模式,请在显示后调用它:

// Make panelReviewImports modal, so that no other part of app will respond.
[[NSApplication sharedApplication] runModalForWindow:self.panelReviewImports];

并在其解雇方法中跟进:

[[NSApplication sharedApplication] stopModal];

但是对于 NSAlert,beginSheetModalForWindow 中的“窗口”是指将作为工作表附加到警报的窗口,该窗口将被冻结直到警报被解除。但应用程序不会被冻结;所有其他窗口将保持可操作。如果您想将警报附加为工作表并冻结 应用程序的其余部分,请按照 beginSheet 代码的简单调用 runModal 并明确使用返回代码,如下所示:

[alert beginSheetModalForWindow:self.window 
                  modalDelegate:self didEndSelector:@selector(abandonmentAlertDidEnd:returnCode:contextInfo:) 
                    contextInfo:nil];
NSInteger returnCode = [alert runModal];
[self abandonmentAlertDidEnd:alert returnCode:returnCode contextInfo:nil];

(当然,您已经实现了放弃AlertDidEnd:returnCode:contextInfo: 代码作为类方法。)

或者,如果您希望警报作为居中面板运行,请单独调用 runModal。

假设您要运行一个面板模式,如果用户提交了无效条目,则随后会发出警报。在显示警报之前,您必须停止模式 - 之后,由于某种原因,对 runModalForWindow 的另一个调用无法正常工作。对于这种情况,您需要一个模态会话

1) 将 NSModalSession 属性添加到您的控制器类,因为 modalSession 必须可以跨多个方法访问。

2) 显示面板后,调用 beginModalSessionForWindow 实例化 modalSession:

self.modalSession = [[NSApplication sharedApplication] beginModalSessionForWindow:self.panelForInput];

3) 用一个调用 runModalSession 的 while 循环跟进,当它的返回不等于 NSRunContinuesResponse 时中断:

while ([[NSApplication sharedApplication] runModalSession:self.modalSession] == NSRunContinuesResponse)
    continue;

当用户单击面板的一个按钮时,循环将中断,应用程序将被释放。(在面板的文本字段中键入将使模态会话保持不变。)

4)在你的按钮处理中,如果用户的输入无效,你用runModal调用一个警报。

5) 在警报调用的正下方,在警报解除后将执行的代码中,您放置了上面使用的相同 while 循环。面板的模态会话恢复。

6) 在您关闭面板的处理中,无论是在有效输入还是取消时,您都会调用 endModalSession,奇怪的是,这还不够;即使您从未调用过 runModalForWindow,您也必须调用 stopModal。

[[NSApplication sharedApplication] endModalSession:self.modalSession];
[[NSApplication sharedApplication] stopModal];
[self.panelForInput close];
4

1 回答 1

3

问题就是答案。我只是发布这个来关闭它。很抱歉扭曲了 stackoverflow 格式。

于 2011-06-15T15:57:59.717 回答