Question

I'm using an OpenPanel to get a file path URL. This works:

[oPanel beginSheetModalForWindow:theWindow completionHandler:^(NSInteger returnCode)
{
 NSURL *pathToFile = nil;

 if (returnCode == NSOKButton)
     pathToFile = [[oPanel URLs] objectAtIndex:0];
}];

This doesn't, resulting in an 'assignment of read-only variable' error:

NSURL *pathToFile = nil;
[oPanel beginSheetModalForWindow:theWindow completionHandler:^(NSInteger returnCode)
{
 if (returnCode == NSOKButton)
     pathToFile = [[oPanel URLs] objectAtIndex:0];
}];
return pathToFile;

In general, any attempt to extract pathToFile from the context of oPanel has failed. This isn't such a big deal for small situations, but as my code grows, I'm forced to stuff everything -- XML parsing, core data, etc -- inside an inappropriate region. What can I do to extract pathToFile?

Thanks.

Was it helpful?

Solution

This doesn't, resulting in an 'assignment of read-only variable' error:

NSURL *pathToFile = nil;
[oPanel beginSheetModalForWindow:theWindow completionHandler:^(NSInteger returnCode)
{
 if (returnCode == NSOKButton)
     pathToFile = [[oPanel URLs] objectAtIndex:0];
}];
return pathToFile;

Yes, because you're trying to assign to the copy of the pathToFile variable that gets made when the block is created. You're not assigning to the original pathToFile variable that you declared outside the block.

You could use the __block keyword to let the block assign to this variable, but I don't think this will help because beginSheetModalForWindow:completionHandler: doesn't block. (The documentation doesn't mention this, but there's no reason for the method to block, and you can verify with logging that it doesn't.) The message returns immediately, while the panel is still running.

So, you're trying to have your completion-handler block assign to a local variable, but your method in which you declared the local variable will probably have returned by the time block runs, so it won't be able to work with the value that the block left will leave in the variable.

Whatever you do with pathToFile should be either in the block itself, or in a method (taking an NSURL * argument) that the block can call.

OTHER TIPS

you can also runModal after you begin the sheet you just need to make sure you end the sheet later. This way you don't have to bend to apple's will, it isn't deprecated and it should still work perfectly.

NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel beginSheetModalForWindow:window completionHandler:nil];
NSInteger result = [openPanel runModal];
NSURL *url = nil;
if (result == NSFileHandlingPanelOKButton) 
{
    url = [openPanel URL];
}
[NSApp endSheet:openPanel];

It seems a little bit like black magic coding but it does work.

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