在 NSDocument 上显示进度指示器 sheet 显示为灰色(尽管仍然有用)

Displaying a progress indicator sheet on NSDocument shows up greyed out (though still serves purpose)

第一次尝试 - beginSheet: completionHandler: Method

我有一个基于文档的应用程序,它会进行适度密集的保存(大约 10-15 秒,但绝对引人注目)。为了让最终用户不认为应用程序已挂起,我在文档上添加了一个显示为 sheet 的进度指示器。在保存文档时,我可以将我的进度指示器显示为 sheet,并且在保存结束时 sheet 会正确消失。但是,该指示器是灰色的。我知道这更像是一个美学问题,但希望能提供有关如何解决此问题的指示。

下面是进度条的截图。它不是蓝色的动画条,而是灰色且静止的。

我在下面列出了相关代码。

显示进度指示器的代码:

- (void) showProgressIndicatorSheet
{
    NSStoryboard *storyboard = [NSStoryboard storyboardWithName:@"Main" bundle:nil];
    modalProgressWindowController = [storyboard instantiateControllerWithIdentifier:@"modalProgressWindowController"];

    NSArray *windowControllers = self.windowControllers;
    if ([windowControllers count] > 0) {
        NSWindowController *controller = windowControllers[0];
        [controller.window beginSheet:modalProgressWindowController.window completionHandler:nil];
    }
}

隐藏代码sheet:

- (void) hideProgressIndicatorSheet
{
    if (modalProgressWindowController) {
        NSArray *windowControllers = self.windowControllers;
        if ([windowControllers count] > 0) {
            NSWindowController *controller = windowControllers[0];
            [controller.window endSheet:modalProgressWindowController.window];
        }
    }
}

显示指标然后在保存时隐藏它的代码:

- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError * _Nullable __autoreleasing *)outError {
    [self showProgressIndicatorSheet];

    /* code to save data to file */

    [self hideProgressIndicatorSheet];
}

第二次尝试 - beginModalSessionForWindow: 方法

正如评论所暗示的那样,可能使用 window sheet 是这里的问题。我四处搜索了一下,发现 beginModalSessionForWindowdocumentation。看起来很有希望,所以我尝试使用它,但遇到进度条变灰的相同问题。我还有一个新问题,尽管调用 [NSApp stopModal].

但我无法停止模式

显示进度指示器的代码:

- (void) showProgressIndicatorSheet
{
    NSStoryboard *storyboard = [NSStoryboard storyboardWithName:@"Main" bundle:nil];
    modalProgressWindowController = [storyboard instantiateControllerWithIdentifier:@"modalProgressWindowController"];

    session = [NSApp beginModalSessionForWindow:modalProgressWindowController.window];
}

关闭模态的代码:

- (void) hideProgressIndicatorSheet
{
    [NSApp endModalSession:session];
}

显示指示器然后在保存时将其关闭的代码:

- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError * _Nullable __autoreleasing *)outError {
    [self showProgressIndicatorSheet];

    BOOL response = NO;
    BOOL beganSave = NO;

    while ([NSApp runModalSession:session] == NSModalResponseContinue) {
        if (!beganSave) {
            beganSave = YES;
            response = [self saveToDBForURL:url];
        }
    }

    [self hideProgressIndicatorSheet];

    return response;
}

saveToDBForURL 内的 stopModal:

- (BOOL)saveTODBForURL: (NSURL *) url {

    /* save method */

    // stop modal after saving is done
    [NSApp stopModal];

    // return whether save was success or not...
    return response;
}

已解决! Willeke 关于调用评论中的所有方法是正确的。但这还不够……我的进度条仍然是灰色的。我在 SO "Document sheet not responding to keyboard events" 上偶然发现了以下 post。事实证明,您必须在 IB 中启用“标题栏”

在 IB 中启用标题栏后,这里是更新后的有效代码(希望没有其他人需要 运行 进入这种怪异状态!):

要显示的代码 sheet

- (void) showProgressIndicatorSheet
{
    NSArray *windowControllers = self.windowControllers;
    if ([windowControllers count] > 0) {
        NSWindowController *controller = windowControllers[0];
        ((BWProgressIndicatorSheetViewController *)modalProgressWindowController.window.contentViewController).progressLabel.stringValue = @"Saving workspace...";
        [controller.window beginSheet:modalProgressWindowController.window completionHandler:nil];
        session = [NSApp beginModalSessionForWindow:modalProgressWindowController.window];
    }
}

关闭代码sheet

- (void) hideProgressIndicatorSheet
{
    [NSApp endModalSession:session];
    if (modalProgressWindowController) {
        NSArray *windowControllers = self.windowControllers;
        if ([windowControllers count] > 0) {
            NSWindowController *controller = windowControllers[0];
            [controller.window endSheet:modalProgressWindowController.window];
        }
    }
}

显示指示器然后在保存时将其关闭的代码

- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError * _Nullable __autoreleasing *)outError {

    [self showProgressIndicatorSheet];

    BOOL response = NO;
    BOOL beganSave = NO;

    while ([NSApp runModalSession:session] == NSModalResponseContinue) {
        if (!beganSave) {
            beganSave = YES;
            response = [self saveToDBForURL:url];
        }
    }

    [self hideProgressIndicatorSheet];

    return response;
}

最后...saveToDBForURL 中的 stopModal:

- (BOOL) saveToDBForURL: (NSURL *) url
{
    // do saving here

    [NSApp stopModal];

    return response;
}