8

NSSavePanelMac App Store 用にアプリをサンドボックス化した後、文字列ファイルを保存するときに問題が発生しました。に設定com.apple.security.files.user-selected.read-writeYESNSOpenPanel正常に動作しています。

ただし、新しいファイルを保存しようとすると、すべてが正常に機能しているように見えますが、あるべき場所に保存されたファイルがありません....

これは、ファイルを保存するために使用しているコードです。

NSSavePanel *save = [NSSavePanel savePanel];

long int result = [save runModal];

if (result == NSOKButton)
{
    NSString *selectedFile = [save filename];
    NSString *fileName = [[NSString alloc] initWithFormat:@"%@.dat", selectedFile];
    NSString *arrayCompleto = [[NSString alloc]initWithFormat:@"bla bla bla"];
    [arrayCompleto writeToFile:fileName
                    atomically:NO
                      encoding:NSUTF8StringEncoding
                         error:nil];
}
4

1 に答える 1

11

まず、-[NSSavePanel filename]セレクターは廃止されました。-[NSSavePanel URL]代わりに使用してください。第二に、-[NSString writeToFile:atomically:encoding:error]何が間違っているかを が伝える方法は、error:(NSError**)引数を使用することです。

また、特にファイル I/O のエラーにも対処する必要があります。これは、コードが 100% 正しい場合でも、ユーザーのシステムにまだエラーがある可能性があり (権限が不十分であるなど)、ユーザーにエラーを提示することでエラーが発生する可能性があるためです。失敗したことを確認してください(理由がわかります)。コードでエラーを処理すると、アプリを回復することもできます。たとえば、貼り付けたコードの下のファイルを (ディスクに書き込んだ後に) 読み込もうとしたが、ユーザーがアクセス権のないネットワーク共有に書き込もうとした場合、アプリがクラッシュする可能性があります。書き込みが失敗したことがわかっている場合は、それに応じて続行できます (おそらく、別の保存場所を求めるプロンプトが表示されます)。

ただし、この場合、次の行が問題だと思います。

NSString *fileName = [[NSString alloc] initWithFormat:@"%@.dat", selectedFile];

アプリがサンドボックス化されている場合、ユーザーは特定のファイルまたは特定のディレクトリのいずれかをサンドボックスに入れるために、開く/保存パネルを介して許可を与える必要があります。あなたがしていることは、ユーザーが書き込み許可を与えたファイルを取得して、「それは素晴らしいが、別のファイルを保存したい」と言って、サンドボックスに違反しています。代わりに、保存パネルで拡張子を設定する必要があります。完全な解決策は次のとおりです。

NSSavePanel *save = [NSSavePanel savePanel];
[save setAllowedFileTypes:[NSArray arrayWithObject:@"dat"]];
[save setAllowsOtherFileTypes:NO];

NSInteger result = [save runModal];

if (result == NSOKButton)
{
     NSString *selectedFile = [[save URL] path];
     NSString *arrayCompleto = @"bla bla bla";

     NSError *error = nil;
     [arrayCompleto writeToFile:selectedFile
                     atomically:NO
                       encoding:NSUTF8StringEncoding
                          error:&error];
}

if (error) {
    // This is one way to handle the error, as an example
    [NSApp presentError:error];
}

将来何か問題が発生した場合はerror、実行時に の値を確認できます。デバッグ中に、if (error)ステートメント内にブレークポイントを設定して、errorオブジェクトの値を確認します ( po errorXcode のデバッガーで a を実行します)。これは、何が問題なのかを理解するのに役立ちます。

于 2012-05-23T12:30:03.917 に答える