重用Apple Sandbox安全范围的书签

时间:2014-06-17 07:51:00

标签: objective-c macos appstore-sandbox

我正在创建一个应用程序,它正在读取应用程序沙箱之外的文件。我需要用户的权限来阅读这些文件,并且通过让用户选择NSOpenPanel中的路径,我可以使用安全范围的书签。

我的问题是,每次应用程序访问同一路径时,我都不希望用户授予我权限。我将书签保存在NSApplicationSupportDirectory文件夹中。

这样可以正常工作,直到用户重新启动计算机,然后似乎保存的书签变得无效。从磁盘加载时书签数据看起来完全正常,但是应用程序需要新的安全范围书签来读取文件,即使应用程序使用书签作为重新启动之前工作的路径。

我正在创建这样的书签:

NSData * bookmark  = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&err];
NSURL* bookmarkUrl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&err]

我正在检查是否可以通过以下方式访问书签:

[url startAccessingSecurityScopedResource];
[[NSFileManager defaultManager] contentsOfDirectoryAtURL:url includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:&err]

if (err && err.code == NSFileReadNoPermissionError)
{
    NSLog(@"No URL access");
    res = NO;
}
else if(err)
{
    NSLog(@"URL validate unexpected error:%@", err);
    res = NO;
}

if (res)
{
    //Bookmark works!
}
[url stopAccessingSecurityScopedResource];

只要我不重启Mac,这就有效。我可以退出应用程序并重新启动它,我的书签仍然有用。但是一旦Mac重新启动,即使我在重新启动之前使用已保存的书签,我也会收到NSFileReadNoPermissionError错误。

有没有办法创建一个在重启Mac时有效的书签?

1 个答案:

答案 0 :(得分:4)

事实证明我在开始和停止调用之间没有平衡。作为startAccessingSecurityScopedResourcedocumentation状态,这可能会使书签无效:

  

警告:您必须平衡对startAccessingSecurityScopedResource方法的每次调用以及对stopAccessingSecurityScopedResource方法的相应调用。如果在不再需要文件系统资源时未能放弃访问权限,则应用程序会泄漏内核资源。如果泄漏了足够的内核资源,您的应用程序将无法将文件系统位置添加到其沙箱中,例如通过Powerbox或安全范围的书签,直到重新启动。

我最终还是将书签存储在NSUserDefaults而不是NSApplicationSupportDirectory文件夹中的文件中。