我正在创建一个应用程序,它正在读取应用程序沙箱之外的文件。我需要用户的权限来阅读这些文件,并且通过让用户选择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时有效的书签?
答案 0 :(得分:4)
事实证明我在开始和停止调用之间没有平衡。作为startAccessingSecurityScopedResource
个documentation状态,这可能会使书签无效:
警告:您必须平衡对
startAccessingSecurityScopedResource
方法的每次调用以及对stopAccessingSecurityScopedResource
方法的相应调用。如果在不再需要文件系统资源时未能放弃访问权限,则应用程序会泄漏内核资源。如果泄漏了足够的内核资源,您的应用程序将无法将文件系统位置添加到其沙箱中,例如通过Powerbox或安全范围的书签,直到重新启动。
我最终还是将书签存储在NSUserDefaults
而不是NSApplicationSupportDirectory
文件夹中的文件中。