ファイル パッケージを Finder から iTunes.app ファイル共有ペインにドラッグすると、UIDocument クラスが関連付けられたファイル ラッパーを読み込もうとしており、それを読み取るコードが、iTunes.app がコンテンツをコピーするよりも速く実行されているように見えます。 . 初期のファイル ラッパー配列には、ラッパー内の 2 つのファイルのうちの 1 つだけが含まれます。
では、コードを「遅く」するにはどうすればよいでしょうか。
performSelector:withObject:AfterDelay:1.0f を使用してテストを実行しましたが、問題なく動作しましたが、非常にリスクが高いように感じます。非常に大きなファイルが iTunes にドラッグされた場合 (非常に大きなファイルとは、私の遅延を超えるファイルを意味します)? 複数のファイルがすべて同時にドロップされた場合はどうなりますか?
ファイルを読み取る準備ができていることをどうにかして見ましたが、AppleのNSFileManagerのドキュメントには次のように書かれています
「操作が成功するかどうかを事前に判断しようとするよりも、操作 (ファイルのロードやディレクトリの作成など) を試み、エラーをチェックし、それらのエラーを適切に処理する方がはるかに優れています。」
しかし、タイミングの問題が発生するのは、構成ファイルラッパーのデコード中にあるため、それを「適切に」処理する方法がわかりません。
私のパッケージ ファイルには、data.dat と info.dat の 2 つのデータ ファイルがあります (この初期段階ですが、さらに多くなる予定です)。ファイルを iTunes.app にドラッグし、View Controller でそれを確認できるところまでコードが機能するようになったとき、data.dat は常に正常にデコードされていましたが、info.dat は見つかりませんでした。ファイルがローカル ドキュメント フォルダ内に配置されると、View Controller は期待どおりにすべてのデータを表示します (つまり、info.dat はファイル ラッパー内にあり、正しく形成されます)。これがタイミングの問題ではないかと疑って、ファイル名の定数とディスク上のファイルの名前を zdata.dat と ainfo.dat に変更しました。
私は遅延読み込みを使用していますが、View Controller は info.dat の内容に即座に関心を持っているため、遅延読み込みは iTunes がコピーを完了するのに十分な遅延ではありません!
私の UIDocument サブクラスの実装から:
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
self.fileWrapper = (NSFileWrapper *)contents;
// Lazy load everything!
_data = nil;
_metadata = nil;
return YES;
}
- (id)decodeObjectFromWrapperWithPreferredFilename:(NSString *)preferredFilename
{
NSFileWrapper *fw = [self.fileWrapper.fileWrappers objectForKey:preferredFilename];
if (!fw) {
NSLog(@"Unexpected error: Couldn't find %@ in the file wrapper for %@", preferredFilename, self.fileURL);
return nil;
}
NSData *data = [fw regularFileContents];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
return [unarchiver decodeObjectForKey:@"data"];
}
- (GSBMetadata *)metadata
{
if (_metadata == nil) {
if (self.fileWrapper != nil) {
// NSLog(@"Loading metadata for %@...",self.fileURL);
_metadata = [self decodeObjectFromWrapperWithPreferredFilename:kGSBMetadataFileName];
} else {
_metadata = [[GSBMetadata alloc] init];
}
}
return _metadata;
}
この問題は、decodeObjectFromWrapperWithPreferredFilename: で発見され、期待されるファイル ラッパーが存在することを確認するためにチェックが行われます。通常、ファイルが破損しているか、アプリのバージョン 2 が別のファイル形式を使用している場合に、これが当てはまります。しかし、これらの状況を適切に処理することは、「偏執的なプログラミングはそのようなことを予期していた」という見出しの下にあり、「ちょっと待てば、すべてのデータが利用可能になる」という見出しの下にはありません。