Question

I am new to NSOpenPanel/NSSavePanel/NSPanel. I am using NSOpenPanel to choose a directory whose files my app will iterate over and do some fairly time-consuming processing.

I can call -close on the panel, but that does not return focus to the main window. I have read a lot about "dismissing" the panel - but I haven't found any methods that "dismiss" rather than "close" a panel or a window.

Is it just that I need to spawn a background thread (NSOperation)?

This is what my -chooseDidEnd:returnCode:contextInfo:

-(void) chooseDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
    {
    [panel orderOut:self];
    [panel release];

    if (returnCode == NSFileHandlingPanelOKButton)
        {
        [progressIndicator startAnimation:self];
        [self doLotsOfTimeConsumingWork:[[panel URL] path]];
        [progressIndicator stopAnimation:self];
        }
    }

While the NSOpenPanel does go away, my NSProgressIndicator does not animate and the main window doesn't come alive until after -doLotsOfTimeConsumingWork: completes.

Update Just looked at NSOperationSample code, and it is looking like that's the way to go.

Was it helpful?

Solution

Two notes:

First, in Cocoa, the event handling and drawing happens on the main thread. Hence it is never a good idea to synchronously call lengthy methods there (which is the reason for your unresponsive UI).
So yes, you should hand off computationally expensive tasks to a secondary thread from this method, like from any IBAction.

Second, calling [panel release] in that method violates Cocoa's rules of object ownership! So if you would be leaking the panel without that call, you should fix that in the method where you're creating the panel.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top