从beginSheetModalForWindow获取URL:

时间:2010-02-02 05:39:14

标签: cocoa asynchronous objective-c-blocks nsopenpanel

我正在使用OpenPanel来获取文件路径URL。这有效:

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

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

这不会导致'只读变量的赋值'错误:

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

通常,任何从oPanel上下文中提取pathToFile的尝试都会失败。对于小情况来说,这不是什么大问题,但随着我的代码的增长,我不得不在不适当的区域内填充所有内容 - XML解析,核心数据等。如何提取pathToFile?

感谢。

2 个答案:

答案 0 :(得分:6)

  

这不会导致'只读变量的赋值'错误:

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

是的,因为您正在尝试分配创建块时生成的pathToFile变量的副本。您没有分配在块外声明的原始pathToFile变量。

您可以使用the __block keyword让块分配给此变量,但我认为这不会有帮助,因为beginSheetModalForWindow:completionHandler:不会阻止。 (文档没有提到这一点,但没有理由阻止该方法,你可以通过日志记录验证它没有。)当面板仍在运行时,消息会立即返回。

所以,你试图让你的完成处理程序块分配给一个局部变量,但你声明局部变量的方法可能会在时间块运行时返回,所以它将无法使用块 left 将保留在变量中的值。

无论你使用pathToFile做什么都应该在块本身中,或者在块可以调用的方法中(采用NSURL *参数)。

答案 1 :(得分:1)

您也可以在开始工作表后运行模式,以确保稍后结束工作表。这样你就不必屈服于苹果的意志,它不会被弃用,它仍然可以完美地运作。

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

它似乎有点像黑魔法编码,但确实有效。