Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MacOS沙盒应用程序:不使用NSOpenPanel访问文件_Macos_Nsurl_File Access_Appstore Sandbox_Security Scoped Bookmarks - Fatal编程技术网

MacOS沙盒应用程序:不使用NSOpenPanel访问文件

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

在基于NSDocument的沙盒应用程序中,无论文档保存在何处,都可以使用NSOpenPanel访问任何兼容的文档。如果没有NSOpenPanel,应用程序只能访问沙盒容器中的文件

由于我的应用程序管理两种类型的子类NSdocument(作为读写器的文本和仅作为读写器的图像),因此我尝试为图像实现一个单独的“Open Recent”菜单。当用户打开它们时,我禁用了它们的普通行为,覆盖了NSDocumentController的
noteNewRecentDocumentURL:(NSURL*)url
方法,以返回图像url的否。这样,只有文本文档出现在普通文件->打开最近的菜单中(当用户选择它们时,将正常打开)。图像列在自定义菜单中

这些图像URL出现问题,因为应用程序是沙盒:应用程序无法直接打开专用菜单中列出的任何图像文件(任何读取操作都会返回-54错误)。可以使用以下方法检查此行为:

[[NSFileManager defaultManager] isReadableFileAtPath:[fileURL path]]
在这种情况下,它总是返回
FALSE
。只有一个例外:当我从专用的“最近打开”菜单中重新打开以前在同一应用程序会话中使用NSOpenPanel打开的文件,然后关闭:在这种情况下
isReadableFileAtPath:
返回
TRUE
,文件可以但当应用程序退出并重新启动时,不能以这种方式访问最近的图像文件

我确定了处理此问题的三种解决方案:

  • 一旦用户通过NSOpenPanel“合法”访问图像文件,就在沙盒容器中移动图像文件。当然,这是可行的,但会阻止用户自行决定文件的位置!同样,在沙盒中复制文件也不是解决方案

  • 在沙箱中为这些文件创建别名。由于我找不到执行此操作的方法,因此无法测试这是否是一个解决方案

  • 禁用应用程序沙盒。但这是更糟糕的解决方案,因为使用沙盒有很多原因


  • 是否有第四种解决方案,可以授权对任何图像文件(无论其位于何处)进行只读访问,而无需禁用沙盒?

    无论发生什么情况,您都无法访问任何文件


    另外,我不确定你的第二个解决方案是什么意思,这可能是你无法遵循它的原因。你可能想引用“安全范围的书签”而不是“别名”,它们工作得很好,这是你应该遵循的路径。

    伊万的建议非常好。阅读几篇文章后(不到一个小时),我可以实现那些安全范围的书签

  • 将该功能添加到沙盒应用程序的授权文件中 将com.apple.security.files.bookmarks.document-scope(或com.apple.security.files.bookmarks.app-scope,或两者)键设置为TRUE

  • 修改文档打开方法(调用NSOpenPanel),如下所示:

  • -(无效)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]同步];
    //…然后按您的方式打开文档
    }
    }
    }
    
  • 修改创建的方法,以便在不使用NSOpenPanel的情况下读取文件
  • -(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,请使用: