【问题标题】:Displaying a progress indicator sheet on NSDocument shows up greyed out (though still serves purpose)在 NSDocument 上显示进度指示表显示为灰色(尽管仍然有用)
【发布时间】:2017-12-31 03:48:51
【问题描述】:

第一次尝试 - beginSheet: completionHandler: Method

我有一个基于文档的应用程序,它可以进行中等强度的保存(大约 10-15 秒,但绝对很明显)。为了让最终用户不会认为应用程序已挂起,我添加了一个进度指示器,该指示器在文档上方显示为工作表。保存文档时,我可以将进度指示器显示为工作表,并且保存结束后工作表会正确消失。但是,该指示器显示为灰色。我知道这更像是一个美学问题,但希望能得到有关如何解决这个问题的建议。

以下是进度指示器的屏幕截图。它不再是蓝色的动画条,而是灰显且静止的。

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

显示进度指示器的代码:

- (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];
    }
}

隐藏工作表的代码:

- (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:方法

正如评论中提到的那样,这里的问题可能是使用窗口表。我做了一些搜索,找到了beginModalSessionForWindow,它是documentation。看起来很有希望,所以我尝试使用它,但同样的问题是进度条是灰色的。我还有一个新问题,尽管调用了[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;
}

【问题讨论】:

  • 我认为那是因为您使用的是窗纸。
  • @ElTomato 我认为你是对的。我发现[NSApp runModalSessionForWindow:(NSWindow *)window] 看起来很有希望。但是我需要弄清楚如何在模态发生时进行保存。稍后会做更多的研究。 developer.apple.com/documentation/appkit/nsapplication/…
  • 更新:所以我尝试了runModalSessionForWindow 并遵循 Apple 的文档,但现在有两个问题:(1)进度条变灰的相同问题,以及(2)我似乎无法保存后让模态消失...尽管调用[NSApp stopModal] 并从循环if ([NSApp runModalSession:session] != NSModalResponseContinue]) 中断,但它仍然存在。我觉得我错过了一些直接的东西。
  • 试试beginSheetbeginModalSessionForWindowrunModalSession,保存,endModalSessionendSheet
  • @Willeke,感谢您的建议,但我仍然看到一个灰色的进度条。我开始怀疑我是否在调用代码以在错误的位置开始工作表......我注意到如果我从 VC 运行工作表,那么我会得到一个正确动画的进度窗口。只有当我从我的 Document 类中调用它时。

标签: objective-c cocoa nsdocument


【解决方案1】:

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

在 IB 中启用标题栏后,这里是更新后的有效代码(希望没有其他人需要遇到这种奇怪的情况!):

显示工作表的代码

- (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];
    }
}

关闭工作表的代码

- (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;
}

【讨论】:

  • 谢谢!我已经关闭了 IB 中的标题栏,所以我的工作表看起来像一张工作表,但后来我不明白为什么我不能与之交互。我仍然可以单击工作表后面的父窗口(一个 NSDocument),但工作表上没有任何内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
  • 2023-01-16
  • 2020-11-26
  • 1970-01-01
  • 1970-01-01
  • 2011-06-19
相关资源
最近更新 更多