I'm building an application that has a feature to open newly taken screenshots. I would like to distribute it using the Mac App Store. Unfortunately, it needs to be sandboxed.
To find the new screenshots I run a NSMetaDataQuery. It returns a few entries but unfortunately I can't get their URL since they are on the Desktop (out of my app's sandbox).
How can I fix this ?
Here is some of the code
query = [[NSMetadataQuery alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidStartGatheringNotification object:query];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidUpdateNotification object:query];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[query setDelegate:self];
[query setPredicate:[NSPredicate predicateWithFormat:@"kMDItemIsScreenCapture = 1"]];
[query startQuery];
numberOfScreenshots = [query resultCount];
[self uploadToAmazonS3:[[[query results]objectAtIndex:([query resultCount]-1)]valueForAttribute:NSMetadataItemURLKey]];
Thanks
Without asking user permission, you can access only Music, Movies, Pictures and Download folders.
You have to ask user, to grant you access to Desktop Folder. Then use mechanism called Security-Scoped Bookmarks, read more about it in AppSandboxDesignGuide.
1 and 2
NSOpenPanel *openPanel = [[NSOpenPanel alloc] init];
[openPanel setCanChooseFiles:NO];
[openPanel setCanChooseDirectories:YES];
[openPanel setCanCreateDirectories:YES];
[openPanel beginWithCompletionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
for (NSURL *fileURL in [openPanel URLs]) {
NSString *filename = [fileURL path];
[[NSUserDefaults standardUserDefaults] setObject:filename forKey:@"PathToFolder"];
NSError *error = nil;
NSData *bookmark = [fileURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
if (error) {
NSLog(@"Error creating bookmark for URL (%@): %@", fileURL, error);
[NSApp presentError:error];
} else {
[[NSUserDefaults standardUserDefaults] setObject:bookmark forKey:@"PathToFolder"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
break;
}
}
}];
3.
NSError *error = nil;
NSData *bookmark = [[NSUserDefaults standardUserDefaults] objectForKey:@"PathToFolder"];
bookmarkedURL = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:nil error:&error];
BOOL ok = [bookmarkedURL startAccessingSecurityScopedResource];
NSLog(@"Accessed ok: %d %@", ok, [bookmarkedURL relativePath]);
So, that sould be it.
After you have allowed access you also need to get the path to the real home folder - all the other file APIs only provide the path to the sandboxed folder even when access to the real one as been enabled. To get around this annoying problem, Apple recommend doing this to get the real home folder:
#include <sys/types.h>
#include <pwd.h>
const char *home = getpwuid(getuid())->pw_dir;
NSString *path = [[NSFileManager defaultManager]
stringWithFileSystemRepresentation:home
length:strlen(home)];
NSString *realHomeDirectory = [[NSURL fileURLWithPath:path isDirectory:YES] path];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With