在沙盒应用中访问桌面

时间:2012-08-28 05:58:37

标签: macos sandbox nsmetadataquery

我正在构建一个具有打开新截图的功能的应用程序。我想使用Mac App Store分发它。不幸的是,它需要沙盒。

要查找新的屏幕截图,我运行NSMetaDataQuery。它会返回一些条目,但遗憾的是我无法获取他们的URL,因为它们位于桌面上(在我的应用程序的沙箱中)。

我该如何解决这个问题?

以下是一些代码

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

由于

2 个答案:

答案 0 :(得分:11)

在不询问用户权限的情况下,您只能访问音乐,电影,图片和下载文件夹。 Entitlements

您必须要求用户授予您访问桌面文件夹的权限。然后使用名为 Security-Scoped Bookmarks 的机制,在AppSandboxDesignGuide中阅读更多相关信息。

  1. 使用NSOpenPanel选择目录。
  2. 保存书签以供将来使用,例如在NSUserDefaults中。
  3. 获取访问权限
  4. 1和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]);
    

    所以,那就是它。

答案 1 :(得分:4)

在您允许访问后,您还需要获取真实主文件夹的路径 - 所有其他文件API仅提供沙盒文件夹的路径,即使已启用对真实文件夹的访问。为了解决这个烦人的问题,Apple建议这样做以获得真正的主文件夹:

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