2012-10-16 6 views
9

私のパッケージ文書にNSFileWrapperを使用しています。場合によっては、パッケージ内のファイルのデータを要求すると、私はnilとなります。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のドキュメントは、この問題について話して表示されます。

This method may return nil if the user modifies the file after you call readFromURL:options:error: or initWithURL:options:error: but before NSFileWrapper has read the contents of the file. Use the NSFileWrapperReadingImmediate reading option to reduce the likelihood of that problem.

しかし、私はこのような状況を防ぐために、上記のコードで変更する必要があるかを理解していません。

失敗した実験

私は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; 
} 
+0

これはクレイジーな推測ですが、保存した後にスポットライトがファイルの属性を変更しているかどうかは疑問です。私はちょっと不思議で、失敗した後にあなたが貯蓄している理由です。代わりにそれを開くのはなぜですか?ちょうどあなたにいくつかのアイデアを試してみることを推測する。 – Dad

+0

野生の推測ですが、私はあなたのオブジェクトが解放されると思います。多分何かがallocで間違っているかもしれません。あなたは分析を試みましたか? allocとinit(そしてself + autoreleaseとrelease)には注意してください。 – Roger

答えて

3

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

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

0

ファイルがディスク上で変更された場合は、nilを取得します(@Geneの説明)。ただし、matchesContentsOfURL:メソッドを使用してこれを確認することができた。

determines whether a disk representation may have changed, based on the file attributes stored the last time the file was read or written. If the file wrapper’s modification time or access permissions are different from those of the file on disk, this method returns YES. You can then use readFromURL:options:error:

このWorking with File Wrappersから、アップルのマニュアルを。イントロからそのセクションに

(注)この:

Because the purpose of a file wrapper is to represent files in memory, it’s very loosely coupled to any disk representation. A file wrapper doesn’t record the path to the disk representation of its contents. This allows you to save the same file wrapper with different URLs, but it also requires you to record those URLs if you want to update the file wrapper from disk later.

ですから、あなたが/必要性を再読み、それにしたい場合は、元のファイルへのURLを保存する必要があります。

結果が表示されないときにmatchesContentsofURL:が返すものは面白いですか?

関連する問題