重用 Apple Sandbox 安全范围的书签

Tho*_*sen 5 macos objective-c 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]
Run Code Online (Sandbox Code Playgroud)

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

[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];
Run Code Online (Sandbox Code Playgroud)

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

有没有办法创建一个在 Mac 重新启动时工作的书签?

Tho*_*sen 5

事实证明,我未能在启动和停止调用之间取得平衡。由于文档startAccessingSecurityScopedResource状态,这可以使booksmarks无效:

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

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