我正在开发一个Mac应用程序,它使用NSOpenPanel提示用户输入文件。应用程序是沙箱(在OSX 10.9.4上测试)。我注意到如果我打开大量文件(~3000),打开的面板会开始向日志发出错误。如果我尝试在chucks中打开少量文件多次,也会发生这种情况。
第一次出现错误后,每次再次使用NSOpenPanel打开文件时,无论有多少文件,都会再次生成这些错误(直到应用程序关闭)。
错误消息如下所示:
TestPanel[98508:303] __41+[NSSavePanel _consumeSandboxExtensions:]_block_invoke: sandbox_consume_fs_extension failed
我尝试打开的每个文件都有一行。
我设法使用一个简单的应用程序重现了这种行为:一个带有单个按钮的沙盒应用程序调用以下代码:
NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection:YES];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
NSLog(@"%lu", [panel.URLs count]);
}];
错误出现在代码到达完成处理程序之前。
似乎我仍然可以从完成处理程序中的面板中获取URL,但它确实污染了系统日志。
修改
似乎此问题与NSOpenPanel / NSSavePanel面板没有直接关系。使用drap / drop with files时会发生非常类似的事情。像这样:
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
...
NSPasteboard *pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSURLPboardType]) {
NSArray *urls = [pboard readObjectsForClasses:@[[NSURL class]] options:nil];
}
...
}
这会在拖动大量文件时生成以下日志消息(&#34;魔术&#34;数字似乎在2900左右):
Consume sandbox extension for itemIdentifier (2937) from pasteboard failed!
与NSOpenPanel一样,在第一次出现之后,每个丢弃的文件都会在日志中生成相同的错误。
编辑2:
@mahal tertin的回复向我指出了正确的方向。问题确实存在于文件数量和安全范围URL资源有限的事实上。然而,似乎找不到合理的解决方案。问题是,当用户点击&#34; OK&#34;在NSOpenPanel上(或删除拖放感知控件上的文件),操作系统已经尝试创建这些安全范围的URL并隐式调用startAccessingSecurityScopedResource
。因此,如果用户尝试打开的文件超过限制,则资源将耗尽,唯一的选择是关闭并重新启动应用程序。
在返回的网址上调用stopAccessingSecurityScopedResource
似乎可以释放资源,但Apple的代表在official developers forums(链接登录后面)后不鼓励使用此解决方案。
似乎应用程序受用户不能打开太多文件的支配。这甚至不是立刻,因为没有批准的方式来释放这些资源。您可以在文档中警告用户,甚至可以通过应用程序内警告警告用户,但是无法防止他们弄乱应用程序并强制重新启动。
因此,如果该应用运行的时间足够长且用户不断打开文件,该应用最终将无法使用。
仍在寻找合理的解决方案。
答案 0 :(得分:8)
在高低搜索并在各个地方询问之后,我将结束这个问题并得出结论,没有答案或解决方法。我发布已知信息以供将来参考。
建议的所有解决方案都只是可以最大限度地减少问题的解决方法,并尝试引导用户不要尝试打开太多文件。但实际上没有任何办法可以解决这个问题。
以下是有关此问题的已知事实:
startAccessingSecurityScopedResource
会自动调用对于使用NSOpenPanel(或拖放机制)打开的文件,并且没有任何内容关闭这些资源stopAccessingSecurityScopedResource
将释放这些资源,但Apple不鼓励这种做法,说它可能与未来的解决方案不兼容苹果似乎真的放弃了这一点,沙盒实施似乎非常草率和短视。
答案 1 :(得分:6)
您遇到的行为是因为安全作用域资源有限:
NSURL - (BOOL)startAccessingSecurityScopedResource告诉
如果泄露了足够的内核资源,您的应用程序将失去其能力 将文件系统位置添加到其沙箱...
目前的限制大致与您的经历相同。看到: What are the current kernel resource limits on security-scoped bookmarks?
为了防止它: