【问题标题】:Cocoa: how to run a modal window while performing a background task?Cocoa:如何在执行后台任务时运行模式窗口?
【发布时间】:2011-08-30 16:00:48
【问题描述】:

我试过打电话

modalSession=[NSApp beginModalSessionForWindow:conversionWindow];
[NSApp runModalForWindow:conversionWindow];

为了获得一个模态转换窗口,阻止用户与应用程序的其余部分进行交互,但这似乎也阻止了代码执行。我的意思是上面显示的代码之后的代码根本没有执行。我怎样才能解决这个问题?我确信这是可能的,因为许多应用程序在执行一些大任务(如视频转换等)时显示出一些进展......

【问题讨论】:

    标签: cocoa macos modal-dialog


    【解决方案1】:

    除非绝对必要,否则请不要使用应用模式窗口。如果可能,请使用一张纸。但是,如果您必须使用模态对话框,您可以通过在模态对话框打开时给它一些时间来运行主运行循环:

    NSModalSession session = [NSApp beginModalSessionForWindow:[self window]];
    int result = NSRunContinuesResponse;
    
    while (result == NSRunContinuesResponse)
    {
        //run the modal session
        //once the modal window finishes, it will return a different result and break out of the loop
        result = [NSApp runModalSession:session];
    
        //this gives the main run loop some time so your other code processes
        [[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
    
        //do some other non-intensive task if necessary
    }
    
    [NSApp endModalSession:session];
    

    如果您的视图需要主运行循环才能运行(想到WebView),这将非常有用。

    但是,请理解模态会话就是这样,在模态窗口关闭并且模态会话结束之前,对beginModalSessionForWindow: 的调用之后的任何代码都不会执行。这是不使用模式对话框的一个很好的理由。

    请注意,您不得在上述代码中的 while 循环中做任何重要的工作,因为这样您将阻塞您的模态会话以及主运行循环,这会将您的应用变成沙滩球城。

    如果你想在后台做一些实质性的事情,你必须使用某种形式的并发,例如使用NSOperation、GCD 后台队列或只是一个普通的后台线程。

    【讨论】:

    • 感谢您详尽的回答。我想我会忘记模态窗口(我从来没有真正喜欢过它们)。
    【解决方案2】:

    如果您希望它在模式窗口启动时运行,您需要在另一个线程中启动后台“任务”。但在大多数情况下,最好的解决方案是不使用模态窗口。

    【讨论】:

    • 另一种选择是简单地告诉conversionWindow 让自己成为关键并把自己排在前面。
    • 这也可能是最好的答案,因为它很简单。无论如何,谢谢!
    猜你喜欢
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多