これを自分の個人的なコードの参照として使用しようとしている人を支援するために、これを更新し始めます。
最新のアップデート
- デバイス同士の通信が停止したら、デバイスを再同期する方法を見つけたと確信しています。以下の回答をすべての詳細で更新します。これが皆さんのお役に立てば幸いです。これを理解するのに、試行錯誤のほぼ 2 か月かかりました。したがって、これを参照して、iCloud を介してデバイスを再び相互に通信させる同様の問題を抱えている他のユーザーと共有してください。これをすべて理解するのにとてつもなく時間がかかったので、できるだけ多くの他の開発者を自分でその場しのぎの修正を作成する必要から救うことができて、とてもうれしく思います。
正しく設定するためのもう 1 つの追加機能
- iCloud データがアカウントに関連付けられているアプリを更新した後、アプリを開いたときにクラッシュが発生する可能性があることがわかりました。これは、iCloud データがデバイス (デバイスがまだ永続ストアをセットアップしていない場所) にすぐにマージしようとするためです。
にとを追加
@property (nonatomic, readwrite) BOOL unlocked;
しました。次に、メソッドとメソッドを変更しました。両方を以下に示します (永続ストアのセットアップの場合は中央、iCloud マージ メソッドの場合は下部)。本質的には、アプリが永続的なストアをセットアップするまで、iCloud がデータをマージしないようにアプリに指示しています。そうしないと、読み取り不能な障害が原因でアプリがクラッシュする可能性があります。AppDelegate.h
@synthesize unlocked;
AppDelegate.m
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
- (void)mergeChangesFrom_iCloud
以下は、persistentStoreCoordinator のセットアップ方法です。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
// here is where you declare the persistent store is not prepared;
self.unlocked = NO;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Maintain_My_Car.sqlite"];
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *options = nil;
NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:nil];
NSString *coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"data"];
if (coreDataCloudContent.length != 0) {
// iCloud enabled;
cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];
options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, @"<bundleIdentifier>.store", NSPersistentStoreUbiquitousContentNameKey, cloudURL, NSPersistentStoreUbiquitousContentURLKey, nil];
} else {
// iCloud not enabled;
options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
}
NSError *error = nil;
[psc lock];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"bad things %@ %@", error, [error userInfo]);
abort();
}
[psc unlock];
// the store is now prepared and ready for iCloud to import data;
self.unlocked = YES;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"iCloud persistent store added");
[[NSNotificationCenter defaultCenter] postNotificationName:@"RefetchAllDatabaseData" object:self userInfo:nil];
});
});
return __persistentStoreCoordinator;
}
<myAppKey>
もちろん、<bundleIdentifier>
実際の値です。このコードを共有する目的でそれらをマスキングしています。
一部の人々がまだこれに問題を抱えていることを知っており、この質問を参考にして、独自の iCloud 対応の Core Data アプリケーションをセットアップする方法を知っているので、個人コードを変更するたびにこれを更新して、皆さんは私のために働くコードを使うことができます。今回の更新では、最初の cloudURL を から に変更[fileManager URLForUbiquityContainerIdentifier:@"<TeamIdentifier>.<bundleIdentifier>"]
し[fileManager URLForUbiquityContainerIdentifier:nil]
、コンテナー情報が資格ファイルから収集されるようにしました。
追加のメソッド
_notificationArray
は次のように定義されています。
@property (nonatomice, strong) NSMutableArray *notificationArray;
@synthesize notificationArray = _notificationArray;
- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {
if (self.unlocked) {
NSManagedObjectContext *moc = [self managedObjectContext];
if (self.notificationArray.count != 0) {
for (NSNotification *note in _notificationArray) {
[moc performBlock:^{
[self mergeiCloudChanges:note forContext:moc];
}];
}
[_notificationArray removeAllObjects];
[moc performBlock:^{
[self mergeiCloudChanges:notification forContext:moc];
}];
} else {
[moc performBlock:^{
[self mergeiCloudChanges:notification forContext:moc];
}];
}
} else {
if (_notificationArray == nil) {
_notificationArray = [[NSMutableArray alloc] init];
}
[_notificationArray addObject:notification];
}
}
- (void)resetStore {
[self saveContext];
__persistentStoreCoordinator = nil;
__managedObjectContext = nil;
// reset the managedObjectContext for your program as you would in application:didFinishLaunchingWithOptions:
myMainView.managedObjectContext = [self managedObjectContext];
// the example above will rebuild the MOC and PSC for you with the new parameters in mind;
}
次に、mergeiCloudChanges:forContext:
方法があります:
- (void)mergeiCloudChanges:(NSNotification *)note forContext:(NSManagedObjectContext *)moc {
// below are a few logs you can run to see what is being done and when;
NSLog(@"insert %@", [[note userInfo] valueForKey:@"inserted"]);
NSLog(@"delete %@", [[note userInfo] valueForKey:@"deleted"]);
NSLog(@"update %@", [[note userInfo] valueForKey:@"updated"]);
[moc mergeChangesFromContextDidSaveNotification:note];
NSNotification *refreshNotification = [NSNotification notificationWithName:@"RefreshAllViews" object:self userInfo:[note userInfo]];
[[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
// do any additional work here;
}
初期の問題
iOS 5.0.1 で iCloud を使用していると、永続ストアに関するエラーが時々発生します。実験を通じて見つけた新しい情報でこれを更新し続けますが、これまでのところ、私が提供した解決策は、アプリを再び適切に機能させる唯一の方法です (残念ながら、jlstrecker の解決策は私にはうまくいきませんでした)。次のようなエラーが表示され始めます。
-NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:: CoreData: Ubiquity: Ubiquity ルート URL を読み込もうとしてエラーが発生しました: file://localhost/private/var/mobile/Library/Mobile%20Documents/./data/. エラー: エラー Domain=LibrarianErrorDomain Code=1 「操作を完了できませんでした。(LibrarianErrorDomain エラー 1 - アイテムのダウンロードを開始できません。)」 UserInfo=0x176000 {NSURL=file://localhost/private/var/mobile/Library /Mobile%20Documents/./data/, NSDescription=アイテムのダウンロードを開始できません。}
私の人生では、なぜ突然これを見ているのか、どうすればそれを止めることができるのかわかりません。両方のデバイスからアプリを削除し、以前にそれらの間で同期していた iCloud データを削除し、アプリに関するバックアップからすべてのデータを削除しました。Xcode を再起動し、両方のデバイスを再起動し、Xcode プロジェクトをクリーンアップしましたが、エラーが表示されるのを止めるものは何もありません。私はこれまでこのエラーを見たことがなく、それを突き止める方法についてオンラインで何かを見つけることができませんでした.
ここでアプリがクラッシュします。
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) { NSLog(@"bad things %@ %@", error, [error userInfo]); abort(); }
ログはヒットせず、アボートもありません。上記のエラーが表示され、アプリ自体が応答しなくなります。誰かが私を正しい方向に向けるのを助けることができれば、私は非常に感謝しています.
以前の問題/質問
これは、ベータ版から 5.0.1 のパブリック リリースへの更新後も続くようです。最後に起こったのは、マネージド コンテキスト データ モデルを変更した後です。まだアプリをリリースしていないことを考えると、わざわざ新しいバージョンのモデルをマージする必要はありませんでした。デバイスでアプリを削除して再インストールしたところ、iCloud コンテナーに保存されているデータとの連携が拒否されました。つまり、ストアがアイテムをダウンロードできないというエラーが表示されました。これは、データ モデル タイプの競合が原因であると考えられますが、これは完全に理にかなっています。したがって、コンテナーを削除せずに、iCloud コンテナー内のデータを削除するだけでよいようです。iCloud データを削除すると、コンテナと App ID が無効になり、すべてが無効になるようです。シンプルに見えたので、jlstrecker の提案に従って新しいコンテナーを作成しようとしましたが、残念ながら、これはまったく役に立ちませんでした。そのため、もう一度、回答で概説した手順を実行する必要がありましたが、これもうまくいきました. しかし、毎回新しいアプリ ID を作成し、プロビジョニング プロファイルを更新しなければならないことの煩わしさを考えると、潜在的に原因を絞り込み、より迅速な解決策にたどり着くために、学んだことを更新することが最善であると考えました。
iCloud > Storage & Backup > Manage Storage に移動し、アプリを削除することがデータを空にする最善の解決策のように見えますが、これを行うとコンテナーが破損し、上記のエラーが発生するようです。そして、これを成功させた後、何度アプリを削除してデバイスに再インストールしても (デバイスに初めて表示されるように見せ、できればコンテナを再作成するため)、アプリを表示することはできません。 [ドキュメントとデータ] リストに再び表示されます。これは、iCloud からデータを削除すると、iCloud がアプリで二度と機能しなくなることを意味する場合、やや懸念されます。これまでのところ、アプリで開発プロファイルのみを使用しているため、おそらく配布プロファイルを使用すると多少の違いが生じる可能性がありますが、確かなことを言う前にそれをテストする必要があります.
これらの新しいアップデートが、ストアのセットアップに問題を抱えている可能性があるすべての人に役立つことを願っています. これまでのところ、私にとってはうまく機能しています。より良い修正や、プロセスをより目立たなくするものを見つけた場合は、必ずさらに更新します.