MacOS沙盒应用程序:不使用NSOpenPanel访问文件
在基于NSDocument的沙盒应用程序中,无论文档保存在何处,都可以使用NSOpenPanel访问任何兼容的文档。如果没有NSOpenPanel,应用程序只能访问沙盒容器中的文件 由于我的应用程序管理两种类型的子类NSdocument(作为读写器的文本和仅作为读写器的图像),因此我尝试为图像实现一个单独的“Open Recent”菜单。当用户打开它们时,我禁用了它们的普通行为,覆盖了NSDocumentController的MacOS沙盒应用程序:不使用NSOpenPanel访问文件,macos,nsurl,file-access,appstore-sandbox,security-scoped-bookmarks,Macos,Nsurl,File Access,Appstore Sandbox,Security Scoped Bookmarks,在基于NSDocument的沙盒应用程序中,无论文档保存在何处,都可以使用NSOpenPanel访问任何兼容的文档。如果没有NSOpenPanel,应用程序只能访问沙盒容器中的文件 由于我的应用程序管理两种类型的子类NSdocument(作为读写器的文本和仅作为读写器的图像),因此我尝试为图像实现一个单独的“Open Recent”菜单。当用户打开它们时,我禁用了它们的普通行为,覆盖了NSDocumentController的noteNewRecentDocumentURL:(NSURL*)ur
noteNewRecentDocumentURL:(NSURL*)url
方法,以返回图像url的否。这样,只有文本文档出现在普通文件->打开最近的菜单中(当用户选择它们时,将正常打开)。图像列在自定义菜单中
这些图像URL出现问题,因为应用程序是沙盒:应用程序无法直接打开专用菜单中列出的任何图像文件(任何读取操作都会返回-54错误)。可以使用以下方法检查此行为:
[[NSFileManager defaultManager] isReadableFileAtPath:[fileURL path]]
在这种情况下,它总是返回FALSE
。只有一个例外:当我从专用的“最近打开”菜单中重新打开以前在同一应用程序会话中使用NSOpenPanel打开的文件,然后关闭:在这种情况下isReadableFileAtPath:
返回TRUE
,文件可以但当应用程序退出并重新启动时,不能以这种方式访问最近的图像文件
我确定了处理此问题的三种解决方案:
是否有第四种解决方案,可以授权对任何图像文件(无论其位于何处)进行只读访问,而无需禁用沙盒?无论发生什么情况,您都无法访问任何文件
另外,我不确定你的第二个解决方案是什么意思,这可能是你无法遵循它的原因。你可能想引用“安全范围的书签”而不是“别名”,它们工作得很好,这是你应该遵循的路径。伊万的建议非常好。阅读几篇文章后(不到一个小时),我可以实现那些安全范围的书签
-(无效)openMyDocument:(id)发件人{
//做你的事
[self.panel beginWithCompletionHandler:^(NSInteger结果){
如果(结果==NSModalResponseOK){
NSURL*selectedURL=[[self.panel URL]对象索引:0];
NSData*书签=零;
n错误*错误=nil;
bookmark=[selectedURL bookmark data with options:nsurl bookmark creation with securityscope
包括资源价值市场:无
relativeToURL:nil//将其设置为应用程序范围
错误:&错误];
如果(错误){
NSLog(@“为URL(%@)创建书签时出错):%@”,selectedURL,Error);
}
NSString*access=[NSString stringWithFormat:@“%@%@”,“access:”,[selectedURL path]];
[[NSUserDefaults standardUserDefaults]setObject:bookmark-forKey:access];
[[NSUserDefaults standardUserDefaults]同步];
//…然后按您的方式打开文档
}
}
}
-(void)openDocumentForScopedURL:(NSURL*)文件URL
NSString*accessKey=[NSString stringWithFormat:@“%@%@”,“Access:”,[fileURL路径]];
NSData*bookmarkData=[[NSUserDefaults standardUserDefaults]objectForKey:accessKey];
NSURL*bookmarkFileURL=nil;
if(bookmarkData==nil){
//未找到安全范围的书签,请提醒用户
返回;
}否则{
n错误*错误=nil;
布尔书签故事;
bookmarkFileURL=[NSURL]
URLByResolvingBookmarkData:bookmarkData
选项:NSURLBookmarksolutionwithsecurityscope
relativeToURL:nil
bookmarkDataIsStale:&bookmarkDataIsStale
错误:&错误];
[书签文件URL startAccessingSecurityScopedResource];
}
//…然后使用bookmarkFileURL打开您的文件
//…做你的事
//重要信息。您必须通知已停止访问
[bookmarkFileURL stoppaccessingsecurityscopedresource];
}
谢谢。我不知道这些书签。它们似乎很难管理,但我会尝试。很好的解决方案。不幸的是,它在Mac/Catalyst的UIKit上似乎不起作用。它说Mac的UIKit中不提供NSURLBookmarkResolutionWithSecurityScope(但在Swift中):(现在提供了!如果您使用的是早期SDK,请使用: