次のように、iCloud をサポートする新しい UIManagedDocument を作成しています。
- ローカル サンドボックス URL を割り当てて初期化する
- iCloud をサポートする永続ストア オプションを設定します: ubiquitousContentNameKey および ubiquitousContentURL。私が一意に生成している名前で、URL は私の ubiquityContainer / CoreData を指しています。
- UIManagedDocument の saveToURL メソッドを使用してサンドボックスにローカルに保存します。
- 完了ハンドラーでは、FileManager の setUbiquitous メソッドで iCloud に移動します。
これまでのところ、このダンスは機能します。(まあ、ちょっと)。setUbiquitous を呼び出した後、成功しなかったというエラーが表示されますが、ドキュメントはクラウドに移動します。完了すると、クラウドに新しいドキュメントが作成されます。他の人のコードで再現できたので、これはバグのようです。
このドキュメントは、クラウド内のすべてのドキュメントを一覧表示する「Documents View Controller」で実際に生成しています。したがって、この新しいドキュメントの最終的な完了ハンドラが完了すると、NSMetadataQuery のおかげでテーブル ビューに表示されます。これまでのところ、かなり標準的な使い方だと思います。
ドキュメントを編集するには、ユーザーはタップして「Single View Document View Controller」に移動します。
このView Controllerでは、ユーザーが編集できるように、選択したドキュメントを「再度開く」必要があります。
したがって、一連の手順をもう一度実行します。
- fileURL を使用して UIManagedDocument を割り当て/初期化します。今回は、URL はクラウドからのものです。
- 上記の手順 2 と同じ設定で、永続ストア オプションを設定します。
ここで、ディスクからドキュメントを開くステップ 3 を試みましたが、失敗しました。ドキュメントは「Closed | SavingError」の状態にあり、開こうとすると失敗します。
ドキュメントの作成はOKで、クラウドへの移動はOKなのに、その後すぐに開くことができない理由を知っている人はいますか? (実際には、アプリのその起動内での試み - 以下を参照してください)。具体的には、UIManagedDocument インスタンスを作成するが、閉じた、開くことができない状態にするのは何ですか?
興味深いことに、アプリを終了して再度起動すると、ドキュメントをタップして再読み込みし、編集することができます。
そして、非常にまれに、作成してから開き、非常に簡単に編集することができます。たとえば、1 つの管理対象オブジェクトを挿入すると、このクローズ | エラー状態を保存しています。
エラー情報:
私は UIManagedDocument をサブクラス化し、 -handleError: メソッドをオーバーライドして、より多くの情報を取得しようとしました。これが私が得たものです (私が入れた他のデバッグ ログと共に):
2012-10-05 14:57:06.000 Foundations[23687:907] 単一ドキュメント ビュー コントローラー ビューが読み込まれました。ドキュメント: fileURL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ documentState: [Closed]
2012-10-05 14:57:06.052 MyApp[23687:907] ドキュメントの状態が変更されました。現在の状態: 5 fileURL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ documentState: [Closed | 保存エラー]
2012-10-05 14:57:06.057 Foundations[23687:5303] UIManagedDocument エラー: ストア名: 新しいドキュメント 34 は既に使用されています。ストア URL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore 使用中ストア URL: file:/ /localhost/var/mobile/Applications/D423F5FF-4B8E-4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore
2012-10-05 14:57:06.059 MyApp[23687:5303] { NSLocalizedDescription = "ストア名: 新しいドキュメント 34 は既に使用されています。\n\tストア URL: file://localhost/private/var/mobile/ Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n\t使用中のストア URL: file://localhost/var/mobile/Applications/D423F5FF-4B8E -4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n"; NSPersistentStoreUbiquitousContentNameKey = "新しいドキュメント 34"; }
エラーは、その後のオープン時に既に存在するストアを作成していると思われるようです。2 回目のオープン時に永続ストアでこれらの iCloud オプションを設定することになっていますか? 私はそのアプローチを試みましたが、うまくいきませんでした。
UIManagedDocument に関するスタンフォード大学の講義を研究しましたが、何が間違っているのかわかりません。
ドキュメントを作成してクラウドに移行する方法は次のとおりです。
- (void) testCreatingICloudDocWithName:(NSString*)name
{
NSURL* cloudURL = [self.docManager.iCloudURL URLByAppendingPathComponent:name isDirectory:YES];
NSURL* fileURL = [self.docManager.localURL URLByAppendingPathComponent:name];
self.aWriting = [[FNFoundationDocument alloc] initWithFileURL:fileURL];
[self setPersistentStoreOptionsInDocument:self.aWriting];
[self.aWriting saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
if (success == YES) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//create file coordinator
//move document to icloud
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
NSError* coorError = nil;
[fileCoordinator coordinateWritingItemAtURL:cloudURL options:NSFileCoordinatorWritingForReplacing error:&coorError byAccessor:^(NSURL *newURL) {
if (coorError) {
NSLog(@"Coordinating writer error: %@", coorError);
}
NSFileManager* fm = [NSFileManager defaultManager];
NSError* error = nil;
NSLog(@"Before set ubiq");
[fm setUbiquitous:YES itemAtURL:fileURL destinationURL:newURL error:&error];
if (!error) {
NSLog(@"Set ubiquitous successfully.");
}
else NSLog(@"Error saving to cloud. Error: %@", error);
NSLog(@"State of Doc after error saving to cloud: %@", self.aWriting);
}];
});
}
}];
}
ここで、persistentStore で iCloud のオプションを設定します。
- (void)setPersistentStoreOptionsInDocument:(FNDocument *)theDocument
{
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:[theDocument.fileURL lastPathComponent] forKey:NSPersistentStoreUbiquitousContentNameKey];
NSURL* coreDataLogDirectory = [self.docManager.coreDataLogsURL URLByAppendingPathComponent:[theDocument.fileURL lastPathComponent]];
NSLog(@"Core data log dir: %@", coreDataLogDirectory);
[options setObject:coreDataLogDirectory forKey:NSPersistentStoreUbiquitousContentURLKey];
theDocument.persistentStoreOptions = options;
}
そして、ここで私はそれを再開しようとしています:
- (void) prepareDocForUse
{
NSURL* fileURL = self.singleDocument.fileURL;
if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
NSLog(@"File doesn't exist");
}
else if (self.singleDocument.documentState == UIDocumentStateClosed) {
// exists on disk, but we need to open it
[self.singleDocument openWithCompletionHandler:^(BOOL success) {
if (!success) {
NSError* error;
[self.singleDocument handleError:error userInteractionPermitted:NO];
}
[self setupFetchedResultsController];
}];
} else if (self.singleDocument.documentState == UIDocumentStateNormal) {
// already open and ready to use
[self setupFetchedResultsController];
}
}