objective-ccocoamodal-dialogbackground-processcocoa-sheet

Custom modal dialog and background operations


I have a Cocoa app with a custom, multi-step account setup that I implemented as a custom modal dialog with a set of views.

The problem is that the background operations (fetching a URL) seem to get stuck. I assume that this is because the application is in a modal mode.

Here the code to start the modal dialog:

[NSApp beginSheet:accountSetupController.window modalForWindow:self.window 
            modalDelegate:nil didEndSelector:NULL contextInfo:NULL];

[accountSetupController beginAccountSetup]; // this later launches the background operation
[NSApp runModalForWindow:accountSetupController.window];

NSApp endSheet:accountSetupController.window];

First of all, is my assumption correct? Is there a way to have the background operation proceed even if the application is running modal?

The actual background operation is not under my control. It is an external API that takes a completion block.


Solution

  • Take a look at the "discussion" section of your call to [NSApplication beginSheet: modalForWindow: ...]:

    Discussion

    This method runs the modal event loop for the specified sheet synchronously. It displays the sheet, makes it key, starts the run loop, and processes events for it. While the application is in the run loop, it does not respond to any other events (including mouse, keyboard, or window-close events) unless they are associated with the sheet. It also does not perform any tasks (such as firing timers) that are not associated with the modal run loop. In other words, this method consumes only enough CPU time to process events and dispatch them to the action methods associated with the modal window.

    To me, this means that background threads and tasks aren't running while this modal session is going. I've run into this problem before with my own modal dialogs trying to access web servers (for registration purposes, if I remember correctly).

    The best solution is to not use modal dialogs if you need to talk to a server asynchronously. If you must use modal dialogs, try to do your communication between modal sheets (i.e. when the user hits "submit", end the sheet and do the server chatting, then bring up the next sheet for the next step).