17

アプリをサンドボックス化し、XML ファイルを使用して複数のファイルのインポート/エクスポートを許可しようとしています。私のアプリ (または別のサンドボックス化されたアプリ) が XML にリストされたファイルにアクセスできるようにするために、シリアル化されたセキュリティ スコープのブックマークも含めます。この回答で説明されているようにシリアル化しています。単体テスト (サンドボックス化されていない) は、問題なく XML データの書き込みと読み取りを行います。私のアプリがブックマークを解決するNSURLと、参照と同様に nil が返されNSErrorます。私はそうあるべきだとは思わないのに、なぜそうなってしまったのでしょうか? でファイル/ディレクトリを選択するようにユーザーに促すことで回避できますNSOpenPanelが、ブックマークを正常に機能させたいと思っています。

テストプロジェクトで再現

自宅で再現するには、Xcode で新しい Cocoa アプリを作成し、プロジェクト内のファイルに次の Gist を使用します: https://gist.github.com/2582589 (適切な next-view ループで更新)

次に、Apple の指示に従って、プロジェクトにコード署名します。ボタンを順番にクリックして、問題 (Apple にrdar://11369377として送信) を再現します。ディスク (アプリのコンテナーの外部) 上の任意のファイルを選択し、エクスポートする 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

前述のように、2 番目のステップ (ブックマークの解決) は完了しますが、両方とも nil のままerrorですresult。サンドボックスを実装してきたので、私が犯した間違いのほとんどNSErrorが返され、バグを解決するのに役立ちました. しかし、今ではエラーは発生せず、URL は解決されません。

その他のトラブルシューティング手順

  • XML ファイルをアプリのサンドボックスに配置しようとしましたが、違いはなかったので、XML ファイルへのアクセスは問題ではありません

  • アプリは ARC を使用しますが、単体テストも同様に成功します。自動解放されたクラス メソッドの代わりに alloc/init も使用してみました (念のため)

  • ブックマークを作成した直後に URL 解決コードを貼り付けたところ、問題なく動作し、セキュリティ スコープの URL が生成されました

  • 最初に作成されたpoブックマーク (シリアル化前) と、逆シリアル化後のブックマークに対して実行したところ、100% 一致しました。シリアル化は問題ではありません

  • 解決の呼び出しを に置き換えましたが、CFURLCreateByResolvingBookmarkData(..)変更はありません。バグの場合は、Core Foundation API と Cocoa レイヤーに存在します。

  • に値を指定しbookmarkDataIsStale:ても効果がない

  • 0forを指定するとoptions:、有効な NSURL が返されますが、セキュリティ スコープがないため、ファイルを読み取る後続の呼び出しは失敗します

    つまり、逆シリアル化されたブックマークは有効に見えます。ブックマーク データが破損していた場合、NSURL で何かできるとは思えません。

  • NSURL.h私が間違っていることを指摘するのに役立つコメントが含まれていませんでした

サンドボックス化されたアプリケーションでセキュリティ スコープのドキュメント ブックマークを使用して成功した人は他にいますか? もしそうなら、あなたは私と何が違うのですか?

OS バージョンのリクエスト

Mountain Lion ベータ版にアクセスできる人は、私のサンプル プロジェクトで同じ (エラーがない) エラーが表示されるかどうかを確認できますか? ライオン以降に修正されたバグなら気にしません。私はまだ開発者プログラムに参加していないため、アクセスできません。その質問に答えることが NDA に違反するかどうかはわかりませんが、そうならないことを願っています。

4

1 に答える 1

6

Gist コードで、AppDelegate.m の次の行 (61 行目) を変更します。

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

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

その後、コードが機能します。

この理由は、 を呼び出す前にドキュメント スコープのブックマークを含む既存の (ただし空の) ファイルが必要なのと同じ理由である可能性があります[anURL bookmarkDataWithOptions]。拡張ファイル属性) をそのファイルに追加します。

そのファイルにデータ (つまりブックマーク URL) をアトミックに書き込む場合、実際には、データは直接ファイルに書き込まれるのではなく、書き込み操作が成功した場合に名前が変更される一時ファイルに最初に書き込まれます。ブックマークを含む (空だが既存の) ファイルに追加されたタグは、一時ファイルに書き込んでから名前を変更するこのプロセス中に失われているようです (したがって、元の空のファイルを削除する可能性があります)。 .

ところで、ドキュメント スコープのブックマークを含む xml ファイルにそれぞれの URL を渡す前に、アプリ スコープのブックマークを作成する必要はありません。

追加:は10.7.4 でcom.apple.security.files.bookmarks.collection-scopeに名前が変更されました。com.apple.security.files.bookmarks.document-scope

于 2012-06-09T21:37:37.023 に答える