多次使用 NSApplication runModalForWindow

Using NSApplication runModalForWindow multiple times

我想知道是否允许使用 runModalForWindow() 启动多个模态循环。在我的应用程序中,我有以下设置:当用户在非模态 window A 中按下按钮 A 时,模态 window B 将使用 runModalForWindow() 打开。在模态 window B 中,有一个按钮 B,如果用户按下这个按钮 B,将使用 runModalForWindow() 打开模态 window C。当模态 window C 打开时,windows A 和 B 应阻止用户输入,当模态 window B 打开时,window A 应被阻止。

这种方法与 runModalForWindow() 一起使用,但我遇到了一个小问题,这让我想知道我在这里做的事情是否被允许。当 modal window C 打开时,我实际上可以将 modal window B 移动到 modal window C 的前面。B 不接受任何输入,但它实际上可以移动到 C 的前面. Window 但是,A 永远无法移动到 B(或 C)的前面...它始终处于后台。

有没有人知道为什么 B 可以移到 C 的前面,而 ​​A 永远不能移到 B 或 C 的前面?是否允许多次使用 runModalForWindow()?

所以简而言之,你有这样的东西:

  1. 删除一些重要数据
  2. Window一个"Delete Data"
  3. Window乙"Are you sure you want to delete the data?"
  4. Window C "Are you VERY VERY sure you want to delete the data?"(让A和B在你删除数据的过程中成为无助的旁观者)?

如果是这样,您可以使用以下两种方法之一:

1) 使用完成的 NSAlert

//ALERT A
[alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
    //handle the response!
    //ALERT B
    [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
        //handle the response!
        //ALERT C
        [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
            //handle the final responde
        }];
    }];
}];

2) 模态 window 使用完成块(参见前面的:Custom Modal Window with Block Completion Handler

i.e. When A closes, handler calls B, when B closes, handler called C etc... all serially

我个人喜欢 (2) 的方式,但 1 是最直接的方法,没有任何可能出错的附加功能。

编辑 抱歉,MD 不喜欢我的代码格式:-/

模态 window 的 level 设置为 NSModalPanelWindowLevel。这是一个 window 级别,高于正常 windows。这就是为什么你不能把 window A 放在 window B 前面。

但是,windowsB和C是同级别的。因此,window 服务器不会强制 window C 总是在 window B 之前。

您可以尝试通过将 window C 的级别设置为高于 NSModalPanelWindowLevel 的级别来解决此问题,但在一般情况下这可能会出现问题。如果您将级别提高太多,它可能最终会出现在系统 UI 元素的前面,例如菜单栏或边框指示器(例如音量变化指示器)。

您还可以使用 addChildWindow(_:ordered) 使 window C 成为 window B 的子代。这将强制执行指定的顺序。它确实有一些副作用。例如,如果您移动 window B,window C 也会移动,以保持相对定位不变。

你没有做任何与 [NSApplication runModalForWindow:] 不合法的事情,在正常情况下 window C 总是在 B 前面,B 总是在 A 前面。但是这可以如果你在 windowB 上调用 orderFront: 会很复杂,在这种情况下 window 被设置为最上面的一个。

检查你的代码,你可能在某处有一个 orderFront:(或者它的一个亲戚:orderFrontRegardless,或 orderWindow:relativeTo:)。另一种可能性是 cocoa 错误,但这种可能性不大。