首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等待[NSAlert beginSheetModalForWindow:...];

等待[NSAlert beginSheetModalForWindow:...];
EN

Stack Overflow用户
提问于 2009-03-03 01:22:57
回答 12查看 16.6K关注 0票数 21

当我像这样显示一个NSAlert时,我立即得到了响应:

代码语言:javascript
复制
int response;
NSAlert *alert = [NSAlert alertWithMessageText:... ...];
response = [alert runModal];

问题是这是应用程序模式的,而我的应用程序是基于文档的。我使用工作表在当前文档的窗口中显示警报,如下所示:

代码语言:javascript
复制
int response;
NSAlert *alert = [NSAlert alertWithMessageText:... ...];
[alert beginSheetModalForWindow:aWindow
                  modalDelegate:self
                 didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
                    contextInfo:&response];

//elsewhere
- (void) alertDidEnd:(NSAlert *) alert returnCode:(int) returnCode contextInfo:(int *) contextInfo
{
    *contextInfo = returnCode;
}

这样做的唯一问题是beginSheetModalForWindow:会立即返回,所以我不能可靠地向用户提问并等待响应。如果我可以将任务分成两个区域,这不是什么大问题,但我不能。

我有一个循环,它处理大约40个不同的对象(在树中)。如果一个对象失败,我希望警报显示并询问用户是继续还是中止(在当前分支继续处理),但是由于我的应用程序是基于文档的,Apple Human Interface指南规定当警报特定于文档时使用工作表。

如何显示警告表并等待响应?

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2009-03-03 02:29:21

不幸的是,您在这里可以做的并不多。基本上,您必须做出决定:重新设计您的应用程序,使其能够以异步方式处理对象,或者使用未经批准的、废弃的体系结构来呈现应用程序模式警报。

如果不知道有关实际设计和如何处理这些对象的任何信息,就很难提供任何进一步的信息。然而,在我的脑海中,可能会有几个想法:

  • 处理另一个线程中的对象,该线程通过某种运行循环信号或队列与主线程通信。如果窗口的对象树被中断,它会通知主线程它被中断了,并等待来自主线程的信号,其中包含要做什么的信息(继续此分支或中止)。然后,主线程显示文档模式窗口,并在用户选择要执行的操作后向进程线程发出信号。

然而,对于你需要的东西来说,这可能真的太复杂了。在这种情况下,我的建议是只使用不推荐使用的用法,但这实际上取决于您的用户需求。

票数 3
EN

Stack Overflow用户

发布于 2011-06-11 00:31:36

我们创建了一个category on NSAlert to run alerts synchronously,就像应用程序模式对话框一样:

代码语言:javascript
复制
NSInteger result;

// Run the alert as a sheet on the main window
result = [alert runModalSheet];

// Run the alert as a sheet on some other window
result = [alert runModalSheetForWindow:window];

代码可以通过GitHub获得,为了完整起见,下面发布了当前版本。

头文件NSAlert+SynchronousSheet.h

代码语言:javascript
复制
#import <Cocoa/Cocoa.h>


@interface NSAlert (SynchronousSheet)

-(NSInteger) runModalSheetForWindow:(NSWindow *)aWindow;
-(NSInteger) runModalSheet;

@end

实现文件NSAlert+SynchronousSheet.m

代码语言:javascript
复制
#import "NSAlert+SynchronousSheet.h"


// Private methods -- use prefixes to avoid collisions with Apple's methods
@interface NSAlert ()
-(IBAction) BE_stopSynchronousSheet:(id)sender;   // hide sheet & stop modal
-(void) BE_beginSheetModalForWindow:(NSWindow *)aWindow;
@end


@implementation NSAlert (SynchronousSheet)

-(NSInteger) runModalSheetForWindow:(NSWindow *)aWindow {
    // Set ourselves as the target for button clicks
    for (NSButton *button in [self buttons]) {
        [button setTarget:self];
        [button setAction:@selector(BE_stopSynchronousSheet:)];
    }

    // Bring up the sheet and wait until stopSynchronousSheet is triggered by a button click
    [self performSelectorOnMainThread:@selector(BE_beginSheetModalForWindow:) withObject:aWindow waitUntilDone:YES];
    NSInteger modalCode = [NSApp runModalForWindow:[self window]];

    // This is called only after stopSynchronousSheet is called (that is,
    // one of the buttons is clicked)
    [NSApp performSelectorOnMainThread:@selector(endSheet:) withObject:[self window] waitUntilDone:YES];

    // Remove the sheet from the screen
    [[self window] performSelectorOnMainThread:@selector(orderOut:) withObject:self waitUntilDone:YES];

    return modalCode;
}

-(NSInteger) runModalSheet {
    return [self runModalSheetForWindow:[NSApp mainWindow]];
}


#pragma mark Private methods

-(IBAction) BE_stopSynchronousSheet:(id)sender {
    // See which of the buttons was clicked
    NSUInteger clickedButtonIndex = [[self buttons] indexOfObject:sender];

    // Be consistent with Apple's documentation (see NSAlert's addButtonWithTitle) so that
    // the fourth button is numbered NSAlertThirdButtonReturn + 1, and so on
    NSInteger modalCode = 0;
    if (clickedButtonIndex == NSAlertFirstButtonReturn)
        modalCode = NSAlertFirstButtonReturn;
    else if (clickedButtonIndex == NSAlertSecondButtonReturn)
        modalCode = NSAlertSecondButtonReturn;
    else if (clickedButtonIndex == NSAlertThirdButtonReturn)
        modalCode = NSAlertThirdButtonReturn;
    else
        modalCode = NSAlertThirdButtonReturn + (clickedButtonIndex - 2);

    [NSApp stopModalWithCode:modalCode];
}

-(void) BE_beginSheetModalForWindow:(NSWindow *)aWindow {
    [self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
}

@end
票数 14
EN

Stack Overflow用户

发布于 2014-05-21 18:54:15

这里有一个NSAlert类别可以解决这个问题(正如Philipp建议的由Frederick提出的解决方案,并由Laurent P.改进:我使用代码块而不是委托,因此它再次被简化)。

代码语言:javascript
复制
@implementation NSAlert (Cat)

-(NSInteger) runModalSheetForWindow:(NSWindow *)aWindow
{
    [self beginSheetModalForWindow:aWindow completionHandler:^(NSModalResponse returnCode)
        { [NSApp stopModalWithCode:returnCode]; } ];
    NSInteger modalCode = [NSApp runModalForWindow:[self window]];
    return modalCode;
}

-(NSInteger) runModalSheet {
    return [self runModalSheetForWindow:[NSApp mainWindow]];
}

@end
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/604768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档