阻止直到NSAlert(显示为模态表)被解雇

时间:2011-11-10 18:42:44

标签: objective-c titanium desktop appcelerator nsalert

我目前通过实现Titanium Appcelerator桌面SDK中缺少的功能来学习(通过实现)objective-c:一种使用自定义按钮文本进行模态对话的方法,并可选择将它们显示为& #34;片材"

然而,当将NSAlert显示为"表时,所有这些都是花花公子并且正常工作。我创建警报的方法立即返回,这就是我想要阻止的。

创建警报的方法返回一个int(来自NSAlert的返回码)。

里面的代码基本归结为:

int returnCode = -1;
if (displayAsSheet) {
    [alert beginSheetModalForWindow:nativeWindow modalDelegate:delegate didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];

} else {
    returnCode = [alert runModal];
}

return returnCode;

modalDelegate是一个实现所需的对象:

- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;

现在只执行returnCode的NSLog。

所以我的问题是:

如何阻止我的方法返回到"表"已被解雇?

或者我是以错误的方式解决这个问题?

5 个答案:

答案 0 :(得分:4)

您必须在显示后启动模式会话,并在关闭工作表后停止会话。

检查一下:https://github.com/incbee/NSAlert-SynchronousSheet,我认为这将有所帮助。

答案 1 :(得分:1)

您可以在beginSheetModalForWindow:...

之后使用此功能
[[NSRunLoop mainRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate distantFuture]]

但是,它会使您的应用中的任何其他窗口无法使用,直到该表单被解除。最好不要阻止这些窗口。

答案 2 :(得分:1)

  

我创建警报的方法立即返回

我相信这是因为,正如@Josh所说,这张纸只相对于它附着的窗口运行模态;它并没有冻结整个应用程序。因此,只要beginSheetModal...执行,方法的其余部分就会继续运行,以return returnCode结束(此处返回-1),而不等待用户响应警报。

返回代码是用户最终推送的警报面板上的按钮(NSAlertFirstButtonReturn,NSAlertSecondButtonReturn等) - 它们列在NSAlert类的末尾REF)。您可以在alertDidEnd方法中使用它来处理用户按下以取消警报的任何按钮。这就是alertDidEnd选择器包含returnCode的原因。

另一方面,当您在runModal块中使用else方法时,您需要明确调用alertDidEnd并将runModal时返回的数字提供给它方法结束 - 即用户解除警报时。

以下是您的代码的修订版本:

int returnCode = -1;
if (displayAsSheet) {
    [alert beginSheetModalForWindow:nativeWindow modalDelegate:delegate didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
    // The selector alertDidEnd has the returnCode int. The alert will then set that code to whatever the user chooses, and will send the altered int on to alertDidEnd.
} 
else {
    // Here, everything stops once runModal is called, until the user dismisses the alert, at which time the runModal method returns the int representing the button the user pushed, and you assign the return to your variable "returnCode."
    returnCode = [alert runModal];
    [self alertDidEnd:alert returnCode:returnCode contextInfo:nil];
}
// Omit the line returning the returnCode.

然后alertDidEnd方法执行以下操作:

- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { 
switch (returnCode) {
    case NSAlertFirstButtonReturn:
        // Do whatever should happen when first button is pushed.
        break;
    case NSAlertSecondButtonReturn: 
        // Do whatever should happen when second button is pushed.
        break;
    default:
        break;
    }
    // Unfreeze things.
    [[NSApplication sharedApplication] stopModal];
}

顺便说一句, 是一种运行工作表并冻结整个应用程序的方式,而不仅仅是工作表附加到的窗口,如果这是你想要的:modal tips

答案 3 :(得分:0)

你正在考虑这种错误的方式。如果您的方法能够等待工作表结束,则应用程序的事件循环将被阻止,并且用户无法与UI进行交互。当您使用runModal作为警报时,会创建一个 new 运行循环来处理警报 - 这就是为什么不能对该应用程序执行任何其他操作。工作表选项的要点是允许用户在显示警报时执行其他操作 - 即,它明确地接管事件处理。

您可以通过附加子窗口来查看伪造纸张。

答案 4 :(得分:0)

您可以尝试设置一个布局,冻结您要在应用上冻结的任何内容(设置冻结=是)直到工作表被移除(设置冻结=否)。
在一般情况下,您不需要阻止某个方法:您只想在用户做出选择之前不要发生某些事情。

例如,我有一个使用陀螺仪的应用程序。它有一些行为,有一些其他行为没有。
所以我有一个布尔值,用于任何使用陀螺仪数据将行为路由到良好行为的方法。我的useGyro布尔值在以下情况下为NO:用户正在选择要启用或不启用的硬件功能,以及当设备上没有陀螺仪时。

我使用的mapView也是如此:如果系统想要找到用户的话,那么有一段时间我会使用用户位置冻结任何行为。当他做出选择时,我改变了那个bool值。