我花了相当多的实验来澄清对Objective-C的"ModalForWindow"语言的一些混淆,以及随后如何使用模态会话.也许以下提示可以节省一些时间:
(如果您不熟悉这个概念:当一个窗口,通常是一个面板,运行模态时,它会阻止应用程序的其他部分响应,直到它被解除.)
"ModalForWindow"在不同的情况下意味着不同的东西.如果您使用loadNibNamed显示由xib定义的面板并且您希望它运行modal,请在显示后调用它:
// Make panelReviewImports modal, so that no other part of app will respond.
[[NSApplication sharedApplication] runModalForWindow:self.panelReviewImports];
Run Code Online (Sandbox Code Playgroud)
并在其解雇方法中采取以下措施:
[[NSApplication sharedApplication] stopModal];
Run Code Online (Sandbox Code Playgroud)
但对于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];
Run Code Online (Sandbox Code Playgroud)
(当然,您将实现了abandonmentAlertDidEnd:returnCode:contextInfo:代码作为类方法.)
或者,如果您希望警报作为居中面板运行,请自行调用runModal.
假设您要运行面板模式,如果用户提交无效条目,则后跟警报.在显示警报之前,您必须先停止模式 - 之后,由于某种原因,另一次调用runModalForWindow无法正常工作.对于此场景,您需要一个模态会话:
1)将NSModalSession属性添加到控制器类,因为modalSession必须可以跨多个方法访问.
2)显示面板后,调用beginModalSessionForWindow来实例化modalSession:
self.modalSession = [[NSApplication sharedApplication] beginModalSessionForWindow:self.panelForInput];
Run Code Online (Sandbox Code Playgroud)
3)使用调用runModalSession的while循环进行跟进,当它的返回值不等于NSRunContinuesResponse时断开:
while ([[NSApplication sharedApplication] runModalSession:self.modalSession] == NSRunContinuesResponse)
continue;
Run Code Online (Sandbox Code Playgroud)
循环将中断,当用户点击其中一个面板按钮时,应用程序将释放.(在面板的文本字段中输入将使模态会话保持不变.)
4)在按钮处理中,如果用户的条目无效,则使用runModal调用警报.
5)紧接警报调用之后,在解除警报后将执行的代码中,您将上面使用的相同的while循环置于其中.小组的模态会话重新开始.
6)在关闭面板的处理中,无论是在有效输入还是取消时,都会调用endModalSession,奇怪的是,这是不够的; 你也必须调用stopModal,即使你从未调用runModalForWindow.
[[NSApplication sharedApplication] endModalSession:self.modalSession];
[[NSApplication sharedApplication] stopModal];
[self.panelForInput close];
Run Code Online (Sandbox Code Playgroud)