You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 07:24:57