I am developing a Mac application that prompts the user for files using the NSOpenPanel. The application is sandboxed (testing on OSX 10.9.4). I noticed that if I open a large amount of files (~3000), the open panel starts to emit errors to the log. This also happens if I try to open less amount of files in chucks for several times.
After the errors start to appear the first time, every time the NSOpenPanel is used again to open files, no matter for how many files, these errors will be generated again (until the application is closed).
The error message looks like this:
TestPanel[98508:303] __41+[NSSavePanel _consumeSandboxExtensions:]_block_invoke: sandbox_consume_fs_extension failed
One line for each file I try to open.
I managed to reproduce this behavior with a simple app: A sandboxed application with a single button invoking the following code:
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]);
}];
The errors appear before the code reaches the completion handler.
It seems that I can still get the URLs from the panel in the completion handler but it really pollutes the system log.
EDIT:
Seems that this problem is not directly related to the NSOpenPanel/NSSavePanel panels. A very similar thing happens when using drap/drop with files. Something like this:
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
...
NSPasteboard *pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSURLPboardType]) {
NSArray *urls = [pboard readObjectsForClasses:@[[NSURL class]] options:nil];
}
...
}
This will generate the following log messages when dragging a large amount of files (the "magic" number seems to be somewhere around 2900):
Consume sandbox extension for itemIdentifier (2937) from pasteboard failed!
As with the NSOpenPanel, after the first occurrence of this, every single file dropped will generate the same error in the log.
EDIT 2:
@mahal tertin's reply pointed me to the right direction. The problem is indeed with the number of files and the fact that security scoped URL resources are limited.
However, there seems to be no reasonable solution found. The problem is that when the user clicks "OK" on the NSOpenPanel (or drops the files on a drag&drop aware control), behind the scenes the OS already attempts to create these security scoped URLs and implicitly calls startAccessingSecurityScopedResource
for you. So if the user attempts to open more files than the limit, the resources are exhausted and the only option is to close and restart the application.
Calling stopAccessingSecurityScopedResource
on the returned URLs seem to free the resources however this solution was discouraged by Apple's representative on the official developers forums (link is behind login).
It seems that the app is at the mercy of the user not to open too many files. And that is not even at once, since there is no approved way to release these resources. You can warn the user in documentation or even with an in-app alert but there is no way to prevent them from messing up the app and forcing a restart.
So if the app runs long enough and the user keeps opening files, the app will eventually become unusable.
Still looking for a reasonable solution for this.