Xamarin.Mac在Xcode14.2沙箱中NSSavePanel不显示返回-2求助
问题
在macOS Ventura(Xcode 14.2)版本之前未出现此问题,推测该版本后沙箱文件访问安全策略的处理流程发生了重大变化。未修改任何代码,但在沙箱中遵循安全策略运行NSSavePanel时,面板完全不显示且返回值为-2,无法正常访问文件夹。相关代码如下:
string filePth = "/Users/hibara/Desktop/sample.jpg"; NSUrl urlPath = NSUrl.FromFilename(filePth); NSError error; var securityScopedUrl = urlPath.CreateBookmarkData(NSUrlBookmarkCreationOptions.WithSecurityScope, null, null, out error); if (securityScopedUrl == null) { Console.WriteLine($"Unable to create security scoped resource: {error.LocalizedDescription}"); return; } var isStale = false; var resolvedUrl = NSUrl.FromBookmarkData(securityScopedUrl, NSUrlBookmarkResolutionOptions.WithSecurityScope, null, out isStale, out error); if (!resolvedUrl.StartAccessingSecurityScopedResource()) { Console.WriteLine($"Unable to start accessing security scoped resource: {error.LocalizedDescription}"); return; } var savePanel = new NSSavePanel { //DirectoryUrl = resolvedUrl, Title = "Save your file", NameFieldStringValue = "Untitled.txt" }; int ret = (int)savePanel.RunModal(); if (ret == 1) { var saveUrl = savePanel.Url; // save file to saveUrl } else if (ret == 0) { Console.WriteLine("User canceled the operation."); } else if ( ret == -2) { //The -2 returns. return; } resolvedUrl.StopAccessingSecurityScopedResource();
解决方法
核心原因
macOS Ventura之后,沙箱对NSSavePanel的权限上下文管理更严格:提前持有安全范围URL的访问权会干扰面板的系统授权流程,导致面板无法正常初始化并返回-2错误。NSSavePanel本身是系统提供的用户授权入口,不需要依赖预加载的安全范围URL。
具体修复步骤
分离安全范围URL与面板逻辑
不要在显示NSSavePanel前启动安全范围URL的访问,将StartAccessingSecurityScopedResource()和StopAccessingSecurityScopedResource()移到用户选择保存路径后、实际读写文件前的代码块中。移除不必要的预授权逻辑
无需提前对现有文件路径创建安全范围书签,NSSavePanel的权限由用户交互后系统自动授予,只需确保Info.plist配置正确权限即可。修正后的代码示例
var savePanel = new NSSavePanel { Title = "Save your file", NameFieldStringValue = "Untitled.txt" }; int ret = (int)savePanel.RunModal(); if (ret == 1) { var saveUrl = savePanel.Url; NSError error; // 仅在需要访问沙箱外路径时,创建并使用安全范围书签 var securityScopedUrl = saveUrl.CreateBookmarkData(NSUrlBookmarkCreationOptions.WithSecurityScope, null, null, out error); if (securityScopedUrl == null) { Console.WriteLine($"Unable to create security scoped resource: {error.LocalizedDescription}"); return; } var isStale = false; var resolvedUrl = NSUrl.FromBookmarkData(securityScopedUrl, NSUrlBookmarkResolutionOptions.WithSecurityScope, null, out isStale, out error); if (resolvedUrl.StartAccessingSecurityScopedResource()) { // 执行文件保存操作 // save file to resolvedUrl resolvedUrl.StopAccessingSecurityScopedResource(); } else { Console.WriteLine($"Unable to start accessing security scoped resource: {error.LocalizedDescription}"); } } else if (ret == 0) { Console.WriteLine("User canceled the operation."); } else if (ret == -2) { Console.WriteLine("Panel failed to display due to sandbox restrictions."); return; }
- 验证Info.plist配置
确保应用的Info.plist包含以下沙箱权限配置:com.apple.security.app-sandbox:设为YES(开启沙箱)com.apple.security.files.user-selected.read-write:设为YES(允许用户选择读写路径)
内容的提问来源于stack exchange,提问作者hibara
相关产品推荐
相关产品推荐

