9

NSFileWrapperパッケージドキュメントに使用しています。パッケージ内のファイルのデータを要求すると、が表示されることがありますnil

これは、パッケージ内のファイルのデータをクエリする方法です。

- (NSData*) dataOfFile(NSString*)filename {
    NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
    return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}

このメソッドは、最終的に一部のファイル(すべてではない)に対してnilを返し始めます。悲しいことに、私は問題を一貫して再現することができませんでした。

それが役立つ場合は、これが私がパッケージを開く方法です:

- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
    self.documentFileWrapper = fileWrapper;
    return YES;
}

パッケージ内のファイルのデータを更新する方法は次のとおりです。

- (void) updateFile:(NSString*)filename withData:(NSData*)data {
    SBFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
    if (fileWrapper) {
        [self.documentFileWrapper removeFileWrapper:fileWrapper];
    }
    NSFileWrapper *fileWrapper = [[SBFileWrapper alloc] initRegularFileWithContents:data ];
    fileWrapper.preferredFilename = filename;
    [self.documentFileWrapper addFileWrapper:fileWrapper];
}

これが私がパッケージを保存する方法です:

- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
    return self.documentFileWrapper;
}

なぜこれが起こっているのですか?それを防ぐ方法はありますか?

のドキュメントは、regularFileContentsこの問題について説明しているようです。

readFromURL:options:error:またはinitWithURL:options:error:を呼び出した後、NSFileWrapperがファイルの内容を読み取る前に、ユーザーがファイルを変更すると、このメソッドはnilを返す場合があります。NSFileWrapperReadingImmediate readingオプションを使用して、その問題の可能性を減らします。

しかし、この状況を防ぐために上記のコードで何を変更する必要があるのか​​わかりません。

失敗した実験

nilを返す場合はドキュメントを保存しようとしましたregularFileContentsが、その後もnilが返されます。このような:

- (NSData*) dataOfFile(NSString*)filename {
    NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
    NSData *data = fileWrapper.regularFileContents;
    if (!data) {
            [self saveDocument:nil];
            fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
            data = fileWrapper.regularFileContents;
    }
    return data;
}
4

2 に答える 2

4

実際に何が起こっているかを確認するのに十分なコードはありません。ただし、根本的な原因は、NSFileWrapperその名前が示すとおり、ファイルまたはディレクトリを表すオブジェクトです。したがって、実際のファイルまたはディレクトリは、メモリ内に存在するオブジェクトと簡単に「非同期」になる可能性があります。NSFileWrapperこれが発生したと判断すると、特定の操作に対して nil を返します。解決策は、NSFileWrapperオブジェクトを短命にすることです。必要なときに作成して開き、できるだけ早く保存して閉じます。

特に、あなたのコードは、パッケージ ディレクトリ ラッパーへのポインターを長時間保持し、それが常に有効であると想定しているようです。ディレクトリが何らかの理由で変更された場合、これは当てはまりません。必要なたびに新しいパッケージ ディレクトリ ラッパーを取得するように再コーディングすれば、問題は解決するはずです。

于 2013-02-03T02:24:38.157 に答える
1

ファイルがディスク上で変更された場合、(@Gene が言うように) nil になります。matchesContentsOfURL:ただし、次のメソッドを使用してこれを確認できます。

ファイルが最後に読み書きされたときに保存されたファイル属性に基づいて、ディスク表現が変更された可能性があるかどうかを判断します。ファイル ラッパーの変更時間またはアクセス許可が、ディスク上のファイルのものと異なる場合、このメソッドは YES を返します。その後、使用できますreadFromURL:options:error:

これは、Working with File Wrappers Apple ドキュメントからのものです。

イントロからそのセクションへのこれに注意してください:

ファイル ラッパーの目的はメモリ内のファイルを表すことであるため、ディスク表現とは非常に疎結合です。ファイル ラッパーは、その内容のディスク表現へのパスを記録しません。これにより、同じファイル ラッパーを異なる URL で保存できますが、後でディスクからファイル ラッパーを更新する場合は、それらの URL を記録する必要もあります。

そのため、再読み込みが必要な場合は、URL を元のファイルに保存する必要があります。

matchesContentsofURL:nil の結果が表示されたときに何が返されるかを聞くのは興味深いことです。

于 2013-02-05T04:31:11.600 に答える