beginSheetModalForWindow:completionHandler:

时间:2015-03-08 14:41:12

标签: macos cocoa

我想学习NSObject可以属于哪个类(NSAlert,NSOpenPanel和NSSavePanel除外)以响应上述调用(如问题标题中所述)。这是我需要做的事情。菜单选择的动作必须是 self.window 的模态,需要额外的用户输入,形式比“确定/取消”更精细的对话(实际工作)为简单起见,代码在示例中省略了:

- (IBAction)myActionDialog:(id)sender
{
NSPanel *panel = self.myActionPanel;
[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {        
    ;        
    if (result == 0){
        ;
    } 
}];
}

然而,编译器警告:

'NSPanel may not respond to beginSheetModalForWindow:completionHandler'

事实证明这是真的,但我不知道如何解决这个问题并编码所需的行为。到目前为止,我一直在寻找合适的文档,但一无所获。非常欢迎任何经验丰富的建议。提前致谢!

更新

这个问题尊重:

[[NSApplication sharedApplication] beginSheet: modalForWindow: modalDelegate: didEndSelector:
                                  contextInfo: ]

方法,几乎​​适用于NSPanel,AFAICT的任何子类。唯一的问题是Apple在宣布它被弃用的同时还没有正确记录一种替代方法,它将普遍取代AFAIK。

2 个答案:

答案 0 :(得分:2)

Apple记录了-[NSApplication beginSheet:...]的替代品。它是NSWindow上的新方法:

-beginSheet:completionHandler:
-beginCriticalSheet:completionHandler:
-endSheet:
-endSheet:returnCode:

在您的情况下,您可以:

[self.window beginSheet:panel completionHandler:^(NSInteger result) {
    if (result == 0){
        ;
    }
}];

答案 1 :(得分:1)

在对该主题进行个别研究后,这是我对这个问题的回答。我发现仔细实现自定义工作表的一个主要问题是在旧的基于模式委托的代码的弃用和失效之间的相当突然和无声的转换,这必须在10.8期间的某个时间发生。 它导致了一个关键的兼容性问题,需要简单的代码分支并避免过度实现新的API枚举,除非出于某种原因确实需要。我理解这样的概念可能会有不同意见,但这是一个实践。我使用Gestalt()命令,因为它适用于10.7和10.10之间的所有系统。意识到有更新,更好,更复杂的方法来确定操作系统运行时,这里有更多相关信息的链接:https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKit/

为了简单起见,我发布了这个,省略了标头声明和界面构建器细节。但希望它清楚:

SInt32 versionMinor;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
versionMinor = 0;
Gestalt(gestaltSystemVersionMinor, &versionMinor);
NSLog(@"Version Minor: %d\n", (int)versionMinor);
}

工作表发布方法:

- (IBAction)postSheet:(id)sender
{
if(versionMinor > 8){
    [self.window beginSheet:self.sheet completionHandler:^(NSInteger result) {
        if (result == 1) [self doSomething];
        if (result == 0) [self doNothing];
    }];
}else [[NSApplication sharedApplication] beginSheet:self.sheet
                                   modalForWindow:self.window
                                    modalDelegate:self
                                   didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
                                      contextInfo:nil
     ];
}

按下OK按钮IBAction:

- (IBAction)ok:(id)sender
{
[self.sheet orderOut:self];
if(versionMinor > 8){NSLog(@">OK Button pressed\n");
    [self.window endSheet:self.sheet returnCode:1];
}else{ NSLog(@"<OK Button pressed\n");
    [NSApp endSheet:self.sheet returnCode: 1];
    }
}

同样,按下取消按钮按下IBAction:

- (IBAction)cancel:(id)sender
{
[self.sheet orderOut:self];
if(versionMinor > 8){ NSLog(@">Cancel Button pressed\n");
    [self.window endSheet:self.sheet returnCode:0];
}else{  NSLog(@"<Cancel Button pressed\n");
    [NSApp endSheet:self.sheet returnCode: 0];
}
}

最后,&#34;遗产&#34; didEndSelector(适用于10.8之前的运行时)

- (void)sheetDidEnd : (NSPanel*)panel returnCode:(NSInteger)returnCode contextInfo:(void*)contextInfo
{
if (returnCode == 1) [self doSomething ];
if (returnCode == 0) [self doNothing ];
}

这适用于10.7到10.10,使用10.8或10.10 SDK构建。在学术界和科学界,OSX 10.7和10.8仍在使用相当多。 希望有人能发现这有用。感谢您的贡献和评论。