【发布时间】:2011-12-22 17:35:48
【问题描述】:
我将开始更新此内容,以帮助那些希望将其用作个人代码参考的人。
最新更新
- 我很确定我找到了一种方法,可以在设备停止相互通信后重新同步设备。我要更新我的 在下面回答所有细节。我非常希望你们都能找到 这很有帮助。花了将近 2 个月的反复试验才弄清楚 这一出。所以请参考并与其他人分享 有类似的问题让设备再次与每个设备通话 其他通过 iCloud。我花了很长时间才弄清楚这一切,所以我 我非常乐意尽可能多地拯救其他开发人员 必须创建自己的临时修复程序。
另一个有助于正确设置的附加功能
- 我发现在更新关联了 iCloud 数据的应用程序后
使用该帐户可能会在打开它时导致崩溃,因为 iCloud
数据将尝试立即合并到设备中(其中
设备尚未设置其持久存储)。我现在添加了
@property (nonatomic, readwrite) BOOL unlocked;到AppDelegate.h和@synthesize unlocked;到AppDelegate.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 时出错: 文件://localhost/private/var/mobile/Library/Mobile%20Documents/./data/。 错误:错误域=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 数据似乎会杀死一切 off,本质上是禁用容器和 App ID。既然看起来 更简单,我尝试按照 jlstrecker 的建议创建一个新容器, 但不幸的是,这根本没有帮助。所以再一次,我不得不 完成我在回答中概述的步骤,这又做了 诡计。但是考虑到必须创建新应用程序是多么烦人 ID 和每次更新配置文件,我认为最好 更新我所学到的可能缩小原因并得到 更快的解决方案。
通过 iCloud > 存储和备份 > 管理存储,然后 删除应用程序似乎是清空应用程序的最佳解决方案 数据,但这样做似乎会破坏容器,导致 上面的错误。而在成功做到这一点之后,不管有多少 有时我删除该应用程序并将其重新安装到设备上(使其 看起来像是第一次出现在设备上,希望 重新创建容器),我永远无法让应用程序显示在 文件和数据列表再次。这有点令人担忧,如果它意味着 任何像这样从 iCloud 中删除数据的人都意味着 iCloud 将不再适用于该应用程序。我只使用一个 到目前为止应用程序上的开发配置文件,所以也许使用 分发配置文件可能会有所不同,但我将不得不 在确定说任何话之前先测试一下。
我希望这些新更新可以帮助任何在设置商店时遇到困难的人。到目前为止,它对我来说效果很好。如果我找到更好的修复或任何使过程更加流畅的东西,我一定会更新更多。
【问题讨论】:
-
我也可以像您一样通过在“管理存储”中删除我的应用程序数据来重现此错误。一个修复似乎是更改 NSPersistentStoreUbiquitousContentURLKey - 例如,我会将后缀从“/data”更改为“/data2”,它将再次开始工作。这当然不是解决方案。
-
slev,在我看来,它就像 iCloud 中的一个错误。报告——rdar://10440734。
-
我和你在一起,@jlstrecker。似乎 iCloud 容器从应用程序中删除了数据以及初始化自身所需的数据。我很高兴看到你报告了这个问题。我也应该这样做还是一个就足够了?
-
另外,我似乎能够通过清除 iCloud 容器来“重置”文件夹:[fileManager removeItemAtURL:cloudUrl error:&error] 所以当 iCloud 刚刚获胜时,这可能是一个很好的“主重置”选项不同步。但是,当您执行此操作时,似乎数据库中的现有内容不会同步 - 只是新内容?
-
@pkclSoft 我会看看我能做些什么来为此目的在 github 上建立一个测试项目。我马上就要放几天假了,然后会继续努力。上传后,我将使用指向源代码的链接更新此线程
标签: iphone core-data ios5 icloud