0

ファイルを作成してから、ファイルに NSURLIsExcludedFromBackupKey 属性を追加しています。これを行うために、HPSFileHelper クラスに次の 2 つのメソッドがあります。

+(void)writeDataToFileWithData:(NSData*)data andFilename:(NSString*)fileName
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

    NSString *documentsDirectory = [paths objectAtIndex:0]; 

    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];

    [data writeToFile:filePath atomically:YES];

    NSURL* fileURL = [NSURL fileURLWithPath:filePath];

    [HPSFileHelper addSkipBackupAttributeToItemAtURL:fileURL]; // Prevent this file from being backed up.
}

+(BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

    NSError *error = nil;
    BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                  forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
    }
    return success;

}

問題は、assert ... fileExistsAtPath が時々失敗することです。おそらくこれは、アサートが実行されるまでにファイルが完全に書き込まれてロック解除されていないことがあるからでしょうか? (大きなファイルの場合?)

この問題をどのようにコーディングすればよいですか?

4

3 に答える 3

1

これを修正する最も簡単な方法は、おそらくメソッドNOatomically:パラメーターに使用することwriteToFile:atomically:です。

  • ファイルをアトミック に書き込むとは、システムがファイルの内容を一時ファイルに書き込み、すべての書き込みが完了したら、ファイルを最終パスに移動することを意味します。 (これは、たとえばファイルの書き込み中にエラーが発生した場合に、最終パスに未完成のファイル コンテンツが含まれないようにするために設計されています)
  • このパラメーターを使用NOすると、システムはファイルを最終的な宛先/パスに直接書き込みます (一時ファイルを使用してから移動するのではなく)。

したがってatomically:YES、一時ファイルを使用して使用する場合、システムを呼び出すaddSkipBackupAttributeToItemAtURL:までに、システムは一時ファイルの書き込みを終了していない可能性があり(したがって、最終パス/宛先への移動を開始していない可能性があります)、アサートが失敗する理由を説明します。

を使用してatomically:NOいる場合、システムは呼び出し時に少なくとも最終パスへの書き込みを開始してaddSkipBackupAttributeToItemAtURL:おり、アサートが失敗しないことを願っています。

于 2012-10-10T22:49:02.410 に答える
1

ドキュメントによるとwriteToFile:atomically:

原子的に

YES の場合、データはバックアップ ファイルに書き込まれ、エラーが発生しないと仮定して、バックアップ ファイルの名前がパスで指定された名前に変更されます。それ以外の場合、データはパスに直接書き込まれます。

単なる仮説ですが、 を呼び出すと[data writeToFile:filePath atomically:YES];、一時ファイルの書き込みが完了したときに呼び出しが返される可能性がありますが、名前の変更がまだ行われていない場合は、 [[NSFileManager defaultManager] fileExistsAtPath: [URL path]]NO が返されます。

私の推測では、通話を に切り替えれば[data writeToFile:filePath atomically:NO]、このバグはなくなるでしょう。

于 2012-10-10T22:52:42.640 に答える
0

その後の調査で、writeToFile が同期的であり、メソッドが戻るまでにファイルが書き込まれていることが明らかになりました。

この問題は、自動生成されたファイル名にスラッシュ文字「/」が含まれていることが原因で発生しました。これは、ファイルの作成に失敗したことを意味します。writeToFile; をアトミックに次のように変更しました。

BOOL bWorked = [data writeToFile:filePath options:NSDataWritingAtomic error:&errorPtr];

if (!bWorked)
{
    NSLog(@"writeDataToFileWithData failed for %@ %@", filePath,errorPtr);
}
于 2012-10-11T08:02:33.800 に答える