Xamarin.Mac 使用安全范围的书签

Xamarin.Mac Using security-scoped bookmarks

微软的官方文档说:

https://docs.microsoft.com/en-us/xamarin/mac/app-fundamentals/sandboxing#using-security-scoped-bookmarks

尝试访问 SandBox 外部的持久性,但它不起作用。

首先,我根据SandBox安全策略使用NSSavePanel.SavePanel,并将我可以访问的URL加入书签。

using (var dlg = NSSavePanel.SavePanel)
{
  dlg.AllowedFileTypes = new[] { "zip" };
  dlg.Prompt = "Authenticate";

  if (dlg.RunModal() > 0)
  {
    NSError error;
    NSData url = dlg.Url.CreateBookmarkData(NSUrlBookmarkCreationOptions.WithSecurityScope, null, null, out error);
  }
}

然后我检索经过访问验证的书签并使它们可访问。

NSData data = new NSData();
NSUrl url = NSUrl.FromBookmarkData(data, NSUrlBookmarkResolutionOptions.WithSecurityScope, null, out bool isStale, out NSError error);

url.StartAccessingSecurityScopedResource();

//...

url.StopAccessingSecurityScopedResource();

但是上面的url只会包含null,会报错

我怎样才能让它发挥作用?

我们是否需要首先在 NSData data 的值中添加任何内容?

你混淆了一些东西。你的代码

using (var dlg = NSSavePanel.SavePanel)
{
  dlg.Message = AppResources.DialogMessageSaveEncryptedFileName;
  dlg.AllowedFileTypes = new[] { "zip" };
  dlg.Prompt = "Authenticate";

  if (dlg.RunModal() > 0)
  {
    NSError error;
    //NSData url = dlg.Url.CreateBookmarkData(NSUrlBookmarkCreationOptions.WithSecurityScope, null, null, out error);
    NSData bookmark = dlg.Url.CreateBookmarkData(NSUrlBookmarkCreationOptions.WithSecurityScope, null, null, out error);
  }
}

dlg.Url 是您要访问的url。 你从 dlg.Url.CreateBookmarkData() 得到的是编码后的书签数据。您可以随心所欲地存储此数据,以便在应用程序启动时持久保存。例如在 UserDefaults 存储:

NSUserDefaults.StandardUserDefaults["bookmark"] = bookmark; 
NSUserDefaults.StandardUserDefaults.Synchronize();

稍后检索:

NSData bookmark = NSUserDefaults.StandardUserDefaults.DataForKey("bookmark");

这是你的数据 放入 NSUrl.FromBookmarkData 以获得 url。

//NSData data = new NSData();
//NSUrl url = NSUrl.FromBookmarkData(data, NSUrlBookmarkResolutionOptions.WithSecurityScope, null, out bool isStale, out NSError error);
NSUrl url = NSUrl.FromBookmarkData(bookmark, NSUrlBookmarkResolutionOptions.WithSecurityScope, null, out bool isStale, out NSError error);    
url.StartAccessingSecurityScopedResource();

//...

url.StopAccessingSecurityScopedResource();

此外,如果您需要继续使用访问权,请注意 CreateBookmarkData 中的 isStale return 值。如果 return 为真,您需要使用 url.CreateBookMarkData 刷新 url 中的书签,并用新书签替换已存储的书签。