【问题标题】:Getting URL From beginSheetModalForWindow:从 beginSheetModalForWindow 获取 URL:
【发布时间】:2010-02-02 05:39:13
【问题描述】:

我正在使用 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?

谢谢。

【问题讨论】:

  • 只需用 __blocklike "__block NSURL *pathToFile = nil" 初始化你的变量

标签: cocoa asynchronous objective-c-blocks nsopenpanel


【解决方案1】:

这不会,导致“分配只读变量”错误:

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 * 参数)。

【讨论】:

  • 谢谢。有趣的是它不遵循范围法则。
  • 单独的作用域是行不通的,因为正如我所说,块将在创建它的方法或函数完成运行后很长时间才运行。因此,当块运行时,该外部范围不再有效。当函数或方法调用块本身时,您可以使用__block,但是当它传递块以排队并稍后运行时,这是行不通的,因为函数或方法在块时已经完成去分配给变量。
  • 这太令人沮丧了。在我完成我的 URL 之前,我基本上被禁止做任何其他事情,无论是否愿意。因此,诸如获取 URL 然后单击按钮以使用它的任务是不可能的。为什么,苹果,为什么?
  • 你不是。异步思考。处理块中的 URL,或从块中调用的方法。不要站在那里等待 URL 到达;这就是运行循环的用途。运行面板后,您所要做的就是返回。
【解决方案2】:

您也可以在开始工作表后运行Modal,您只需要确保稍后结束工作表。这样你就不必屈服于苹果的意志,它没有被弃用,它应该仍然可以完美地工作。

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

这看起来有点像黑魔法编码,但确实有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 2012-06-19
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多