应用沙盒:文档范围的书签不解析;不返回任何错误 [英] App Sandbox: document-scoped bookmark not resolving; not returning any error

查看:354
本文介绍了应用沙盒:文档范围的书签不解析;不返回任何错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是沙箱我的应用程序,并试图允许导入/导出多个文件,使用XML文件来引用它们。要允许我的应用程序(或另一个沙盒应用程序)访问XML中列出的文件,我还包括序列化的安全范围书签。我按照此答案中所述的方式对其进行序列化,并且我的单元测试(不是 沙盒)写入和读取XML数据没有问题。当我的应用程序解析书签时,返回的 NSURL 是nil,以及 NSError 引用。因为我不相信应该是这样,为什么会发生?我可以通过提示用户选择一个具有 NSOpenPanel 的文件/目录来解决它,但我仍然希望得到的书签,他们应该工作。



在测试项目中再现



要在家中重现,请创建一个新的Cocoa应用在Xcode中,并对项目中的文件使用以下Gist: https://gist.github.com/2582589 (< )



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



希望你们能够帮助我弄清楚我做错了什么。或者我做错了,框架错误地保持自己,或者我做的正确,它完全破碎。我尽量不要指责框架,那么是什么呢?



将XML导出为

code> docURL :

  //用户选择XML(docURL)目标with NSSavePanel 

[targetURL startAccessingSecurityScopedResource];
NSData * bookmark = [targetURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includeResourceValuesForKeys:nil
relativeToURL:docURL
error:& error];
[targetURL stopAccessingSecurityScopedResource];从 docURL :导入XML p>

  //用户从NSOpenPanel中选择XML(docURL)后

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

我试着用 [docURL ..AccessingSecurityScopedResource] ,没有什么区别(像预期的那样,因为在打开面板中选择docURL之后,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

如上所述,第二步(解析书签)完成,但保留错误 result nil。由于我一直在实施沙盒,大多数错误导致了 NSError 被返回,这有助于我解决这个错误。



ul>
  • 我尝试将XML文件放入我的应用程序的沙箱中,这没有什么区别,因此访问XML文件不是问题


  • 应用程序使用ARC,但单元测试也是成功的。我尝试使用alloc / init代替自动释放的类方法(只是为了防止这种情况)


  • 我在创建书签后立即粘贴了URL解析代码,


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


  • 我用 CFURLCreateByResolvingBookmarkData(..)


  • 指定值 bookmarkDataIsStale:

    / code>无效


  • 如果我为 0 > options:,然后我 do 获取有效的NSURL,但它没有安全范围,因此,仍然失败



    换句话说,反序列化书签似乎有效。


  • NSURL.h




  • 其他使用安全性的人范围内的文档书签在沙箱应用程序中成功?



    操作系统版本请求



    有人可以访问Mountain Lion beta验证我的示例项目是否显示相同(缺少)错误?如果这是一个已经修复了狮子之后的错误,我不会担心。我还没有在开发人员程序,所以没有访问权限。

    解决方案

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

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

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

    然后,您的代码就会工作。这种情况的原因可能与在调用[anURL之前)需要包含文档范围书签的现有文件(但是空文件)相同的原因。

    bookmarkDataWithOptions]:在创建NSData实例时,ScopedBookmarkAgent会向该文件添加一些东西(如标签,可能是扩展文件属性)。



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



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



    添加:com.apple.security.files.bookmarks.collection-scope已在10.7中重命名为com.apple.security.files.bookmarks.document-scope。 4。


    I'm sandboxing my app, and trying to allow for import/export of multiple files, using an XML file to refer to them. To allow my app (or another sandboxed app) access to the files listed in the XML, I'm also including a serialized security-scoped bookmark. I'm serializing it as described in this answer, and my unit tests (which are not sandboxed) write and read the XML data without issue. When my app resolves the bookmark, the NSURL returned is nil, as is the NSError reference. Since I don't believe that should be the case, why is it happening? I can work around it by prompting the user to select a file/directory with an NSOpenPanel, but I'd still like to get the bookmarks to work as they should.

    Reproduced in a test project

    To reproduce at home, create a new Cocoa app in Xcode, and use the following Gist for the files in the project: https://gist.github.com/2582589 (updated with a proper next-view loop)

    Then, follow Apple's instructions to code-sign the project. You reproduce the problem (which I submitted to Apple as rdar://11369377) by clicking the buttons in sequence. You pick any file on disk (outside the app's container), then an XML to export to, and then the same XML to import.

    Hopefully you guys will be able to help me figure out what I'm doing wrong. Either I'm doing something wrong and the framework is erroneously keeping to itself, or I'm doing it right and it's totally broken. I try not to blame the framework, so which is it? Or is there another possibility?

    Sample Code

    Exporting the XML to 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];
    

    Importing the XML from docURL:

    // After the user selected the XML (docURL) from an NSOpenPanel
    
    NSURL *result = [NSURL URLByResolvingBookmarkData:bookmarkData
                                              options:NSURLBookmarkResolutionWithSecurityScope
                                        relativeToURL:docURL
                                  bookmarkDataIsStale:nil
                                                error:&error];
    

    I tried surrounding this call with[docURL ..AccessingSecurityScopedResource], which didn't make a difference (as expected, since the docURL is already within scope after having been selected in the Open Panel

    Also, I specify the following in my app.entitlements file:

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

    As mentioned above, the second step (resolving the bookmark) completes, but leaves both error and result nil. As I've been implementing sandboxing, most of the mistakes I've made have resulted in an NSError being returned, which helped me to resolve the bug. But now there's no error, and no URL is resolved.

    Miscellaneous troubleshooting steps

    • I tried placing the XML file into my app's sandbox, which didn't make a difference, so access to the XML file is not the problem

    • The app uses ARC, but so do the unit tests, which succeed. I tried using an alloc/init instead of the autoreleased class method, too (just in case)

    • I pasted the URL resolution code immediately after creating the bookmark, and it runs fine, producing a security-scoped URL

    • I did a po on the originally created bookmark (before serialization), and then on the bookmark after deserialization, and they match 100%. Serialization is not the problem

    • I replaced the resolution call with CFURLCreateByResolvingBookmarkData(..), with no change. If it is a bug, it's present in the Core Foundation API as well as the Cocoa layer

    • Specifying a value for bookmarkDataIsStale: has no effect

    • If I specify 0 for options:, then I do get back a valid NSURL, but it has no security scope, and therefore subsequent calls to read the file do still fail

      In other words, the deserialized bookmark does appear to be valid. If the bookmark data were corrupted, I doubt NSURL would be able to do anything with it

    • NSURL.h didn't contain any useful comments to point out something I'm doing wrong

    Is anyone else using security-scoped document bookmarks in a sandboxed application with success? If so, what are you doing differently than I am?

    OS Version Request

    Can someone with access to the Mountain Lion beta verify whether or not my sample project shows the same (lack of an) error? If it's a bug that has been fixed after Lion, I won't worry about it. I'm not in the developer program yet, and so don't have access. I'm not sure if answering that question would violate the NDA, but I hope not.

    解决方案

    In your Gist code, change the following line in AppDelegate.m (line 61):

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

    to

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

    Your code will then work.

    The reason for this is likely the same reason for which it is necessary to have an existing (but empty) file that will contain the document-scoped bookmarks before calling [anURL bookmarkDataWithOptions]: While creating the NSData instance, the ScopedBookmarkAgent adds something (like a tag, probably an extended file attribute) to that file.

    If you write data (i.e. the bookmark URLs) to that file atomically, in fact they're written not directly to the file but first to a temporary file that is renamed if the write operation was successful. It seems that the tag that has been added to the (empty, but existing) file that will contain the bookmarks is getting lost during this process of writing to a temporary file and then renaming it (and thereby likely deleting the original, empty file).

    By the way: It shouldn't be necessary to create app-scoped bookmarks before passing the respective URLs to the xml file containing the document-scoped bookmarks.

    Addition: com.apple.security.files.bookmarks.collection-scope has been renamed to com.apple.security.files.bookmarks.document-scope in 10.7.4.

    这篇关于应用沙盒:文档范围的书签不解析;不返回任何错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆