我将开始更新它以帮助那些寻求将其用作自己个人代码的参考的人。
最新更新
- 我很确定我已经找到了一种方法,可以在设备停止相互通信后重新同步设备。我将在下面使用所有详细信息更新我的答案。我非常希望你们都觉得这很有帮助。花了将近 2 个月的反复试验才弄清楚这一点。因此,请参考并与其他遇到类似问题的人分享,让设备再次通过 iCloud 相互交谈。我花了很长时间才弄清楚这一切,所以我很高兴尽可能多地让其他开发人员免于创建自己的临时修复程序。
另一个有助于正确设置的补充
- 我发现在更新具有与帐户关联的 iCloud 数据的应用程序后,打开它可能会导致崩溃,因为 iCloud 数据会尝试立即合并到设备中(设备尚未设置其持久存储)。我现在添加了
@property (nonatomic, readwrite) BOOL unlocked;
toAppDelegate.h
和@synthesize unlocked;
toAppDelegate.m
。然后我更改了我的- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
方法以及我的- (void)mergeChangesFrom_iCloud
方法,这两者都将在下面显示(中间为持久存储设置,底部为 iCloud 合并方法)。从本质上讲,我是在告诉应用程序在应用程序设置其持久存储之前阻止 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/。错误:Error 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(); }
日志永远不会被命中,也不会中止。我只是看到上面的错误,应用程序本身变得无响应。如果有人能帮助我指出正确的方向,我将不胜感激。
以前的问题/问题
即使在从 beta 版更新到 5.0.1 的公开版本之后,这种情况似乎仍在继续。上一次发生在我身上是在更改了我的托管上下文数据模型之后。考虑到我还没有发布应用程序,我没有费心合并模型的新版本。我刚刚在我的设备上删除并重新安装了该应用程序,但它拒绝与存储在 iCloud 容器中的数据合作,我的意思是我收到了一个错误,即商店无法下载项目。我想这是由于数据模型类型冲突造成的,这很有意义。所以看起来你只需要摆脱 iCloud 容器中的数据而不摆脱容器。删除 iCloud 数据似乎会扼杀一切,实质上是禁用容器和 App ID。因为看起来比较简单,我尝试按照 jlstrecker 的建议创建一个新容器,但不幸的是,这根本没有帮助。所以再一次,我必须完成我在答案中概述的步骤,这又成功了。但是考虑到每次都必须创建新的 App ID 和更新配置文件是多么烦人,我认为最好更新我所学到的知识,以缩小原因并找到更快的解决方案。
通过 iCloud > Storage & Backup > Manage Storage,然后删除应用程序似乎是清空数据的最佳解决方案,但这样做似乎会损坏容器,导致上述错误。成功完成此操作后,无论我删除应用程序并将其重新安装到设备多少次(使其看起来像是第一次出现在设备上并希望重新创建容器),我永远无法让应用程序显示再次在文档和数据列表中。这有点令人担忧,这是否意味着任何从 iCloud 中删除数据的人都意味着 iCloud 将不再适用于该应用程序。到目前为止,我只在应用程序上使用开发配置文件,因此使用分发配置文件可能会有所不同,但我必须先测试一下,然后才能确定。
我希望这些新的更新可以帮助任何在设置商店时遇到困难的人。到目前为止,它对我来说效果很好。如果我找到更好的修复或任何使过程更加流畅的东西,我一定会更新更多。