17

我正在对我的应用程序进行沙箱处理,并尝试允许导入/导出多个文件,使用 XML 文件来引用它们。为了允许我的应用程序(或其他沙盒应用程序)访问 XML 中列出的文件,我还包括一个序列化的安全范围书签。我正在按照这个答案中的描述对其进行序列化,并且我的单元测试(不是沙盒)可以毫无问题地写入和读取 XML 数据。当我的应用程序解析书签时,NSURL返回为零,NSError参考也是。既然我不认为应该是这样,为什么会这样?我可以通过提示用户选择带有 . 的文件/目录来解决这个问题NSOpenPanel,但我仍然希望书签能够正常工作。

在测试项目中重现

要在家中重现,请在 Xcode 中创建一个新的 Cocoa 应用程序,并为项目中的文件使用以下 Gist:https ://gist.github.com/2582589 (使用正确的 next-view 循环更新

然后,按照Apple 的说明对项目进行代码签名。您可以通过按顺序单击按钮来重现问题(我以rdar://11369377的形式提交给 Apple)。您选择磁盘上的任何文件(在应用程序容器之外),然后选择要导出到的 XML,然后要导入相同的 XML。

希望你们能够帮助我弄清楚我做错了什么。要么我做错了,框架错误地保持自己的状态,要么我做对了,但它完全坏了。我尽量不怪框架,那是什么?还是有另一种可能?

示例代码

将 XML 导出到docURL

// After the user picks an XML (docURL) destination with NSSavePanel

[targetURL startAccessingSecurityScopedResource];
NSData *bookmark = [targetURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
                       includingResourceValuesForKeys:nil
                                        relativeToURL:docURL
                                                error:&error];
[targetURL stopAccessingSecurityScopedResource];

从以下位置导入 XML docURL

// After the user selected the XML (docURL) from an NSOpenPanel

NSURL *result = [NSURL URLByResolvingBookmarkData:bookmarkData
                                          options:NSURLBookmarkResolutionWithSecurityScope
                                    relativeToURL:docURL
                              bookmarkDataIsStale:nil
                                            error:&error];

我尝试用 包围这个调用[docURL ..AccessingSecurityScopedResource],这没有任何区别(正如预期的那样,因为在打开面板中选择 docURL 后,它已经在范围内

另外,我在我的app.entitlements文件中指定了以下内容:

com.apple.security.files.user-selected.read-write
com.apple.security.files.bookmarks.app-scope
com.apple.security.files.bookmarks.collection-scope

如上所述,第二步(解析书签)完成了,但两者都为errorresult。由于我一直在实施沙盒,所以我犯的大多数错误都导致NSError返回,这帮助我解决了这个错误。但是现在没有错误,也没有解析 URL。

其他故障排除步骤

  • 我尝试将 XML 文件放入我的应用程序的沙箱中,但没有任何区别,因此访问 XML 文件不是问题

  • 该应用程序使用 ARC,但单元测试也是如此,它成功了。我也尝试使用 alloc/init 而不是 autoreleased 类方法(以防万一)

  • 我在创建书签后立即粘贴了 URL 解析代码,它运行良好,生成了一个安全范围的 URL

  • po在最初创建的书签(序列化之前)上做了一个,然后在反序列化后的书签上做了一个,它们匹配 100%。序列化不是问题

  • 我用 替换了分辨率调用CFURLCreateByResolvingBookmarkData(..),没有任何变化。如果它是一个错误,它存在于 Core Foundation API 以及 Cocoa 层中

  • 指定值bookmarkDataIsStale:无效

  • 如果我指定0for options:,那么我返回一个有效的 NSURL,但它没有安全范围,因此后续读取文件的调用仍然失败

    换句话说,反序列化的书签似乎是有效的。如果书签数据已损坏,我怀疑 NSURL 是否可以用它做任何事情

  • NSURL.h没有包含任何有用的评论来指出我做错了什么

是否有其他人在沙盒应用程序中成功使用安全范围的文档书签?如果是这样,你在做什么和我不一样?

操作系统版本请求

可以访问 Mountain Lion 测试版的人可以验证我的示例项目是否显示相同(缺少)错误?如果是 Lion 之后修复的 bug,我就不用担心了。我还没有加入开发者计划,所以没有访问权限。我不确定回答这个问题是否会违反 NDA,但我希望不会。

4

1 回答 1

6

在您的 Gist 代码中,更改 AppDelegate.m 中的以下行(第 61 行):

[xmlTextFileData writeToURL:savePanel.URL atomically:YES];

[xmlTextFileData writeToURL:savePanel.URL atomically:NO];

然后您的代码将起作用。

其原因可能与在调用之前需要有一个包含文档范围书签的现有(但为空的)文件的原因相同[anURL bookmarkDataWithOptions]:在创建 NSData 实例时,ScopedBookmarkAgent 添加了一些东西(比如标签,可能扩展文件属性)到该文件。

如果您以原子方式将数据(即书签 URL)写入该文件,实际上它们不是直接写入该文件,而是首先写入一个临时文件,如果写入操作成功,该临时文件将被重命名。在写入临时文件然后重命名它的过程中,似乎已添加到包含书签的(空但现有的)文件中的标签丢失了(因此可能会删除原始的空文件) .

顺便说一句:在将相应的 URL 传递给包含文档范围书签的 xml 文件之前,不必创建应用范围的书签。

补充:com.apple.security.files.bookmarks.collection-scopecom.apple.security.files.bookmarks.document-scope在 10.7.4 中重命名为。

于 2012-06-09T21:37:37.023 回答