将iCloud Store迁移到本地商店,并确保每次启动应用程序时都有数据

基于这里的问题: 将iCloud数据迁移到本地存储,并停止iCloud仍然响应将iCloud存储转移到本地存储,并确保iCloud通知被禁用,我有下一个scheme,我卡住了。

问题

现在,当用户在第一台设备上运行应用程序时,他们会在开始时询问是否要启用iCloud。 如果select“是”,则将数据迁移到iCloud。 如果用户在第二台设备上连接,则会在开始时询问是否要使用iCloud,如果select是,则会同步跨第一台设备的数据。

如果第二个设备上的用户决定不再使用iCloud,他们可以在该设备的应用程序中专门导航和closuresiCloud。 这在后端将他们的数据从iCloud商店迁移到本地商店。 从用户的angular度来看,他们所有的数据都存在(无论是存储在云中还是本地对用户而言都不重要)。

问题是当我迁移我的数据时,它成功迁移到本地iCloud存储并成功停止侦听iCloud通知。 这方面的工作,这是在我以前问(我的iCloud数据迁移到本地存储和停止iCloud仍然响应 )的堆栈溢出问题。

具体的问题是,当用户重新启动应用程序,应用程序现在是空的,没有数据。 这当然不是预期的效果。

为了完整起见,“迁移代码”基于另一个堆栈溢出问题,但为了方便,我在此粘贴:

- (void)migrateiCloudStoreToLocalStore { NSLog(@"Migrate iCloudToLocalStore"); NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores.lastObject; //NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"]; NSURL *storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL]; NSLog(@"Current Store URL (before iCloud to Local migration): %@", [storeURL description]); NSDictionary *localStoreOptions = nil; localStoreOptions = @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES, NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES}; NSPersistentStore *newStore = [self.persistentStoreCoordinator migratePersistentStore:store toURL:storeURL options:localStoreOptions withType:NSSQLiteStoreType error:nil]; [self reloadStore:newStore]; } - (void)reloadStore:(NSPersistentStore *)store { NSLog(@"Reload Store"); NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"]; NSDictionary *localStoreOptions = nil; localStoreOptions = @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES, NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES}; if (store) { [self.persistentStoreCoordinator removePersistentStore:store error:nil]; } [self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:localStoreOptions error:nil]; storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL]; NSLog(@"Current Store URL (after iCloud to Local migration): %@", [storeURL description]); NSLog(@"Done reloading"); [[NSUserDefaults standardUserDefaults]setBool:YES forKey:@"MigratedFromiCloudToLocal"]; [[NSUserDefaults standardUserDefaults]synchronize]; 

所有的魔法发生在persistentStoreCoordinator ..这是混乱,但我需要得到这部分工作,然后这可以清理:

  - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"]; NSError *error = nil; NSURL *iCloud = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: nil]; NSDictionary *options = nil; if ((iCloud) && (![[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && (![[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"])) { NSLog(@"In the persistent store, iCloud is enabled in the app device but not yet in the app and not on the latest version"); options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES}; } else if ((iCloud) && ([[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && ([[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"])) { NSLog(@"In the persistent store, iCloud is enabled, we're using iCloud from the Tutorial and we're on the latest version"); NSURL *cloudURL = [self grabCloudPath:@"iCloud"]; options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES, NSPersistentStoreUbiquitousContentURLKey: cloudURL, NSPersistentStoreUbiquitousContentNameKey: @"EnvyCloud"}; } else if ((iCloud) && (![[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && ([[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"])) { NSLog(@"In the persistent store, iCloud is enabled, we're on the latest version, btu we're not using icloud in the App"); options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES}; } else { NSLog(@"iCloud is just not enabled"); options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES}; } _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); //abort(); } return _persistentStoreCoordinator; } 

因此,在用户在应用程序中启用iCloud,然后决定不在此特定设备上使用iCloud的情况下,iCloud通知将被删除,商店将从iCloud Store迁移到本地存储,并设置NSUserDefaults。 在应用程序的下一次启动..第三if语句在persistentStoreCoordinator评估为正确说我们是在最新版本,真正的iCloud启用(在设备),但不是在应用程序,但它显示应用程序绝对没有任何条目,有点像开始新鲜。

我如何克服这一点,并返回刚刚迁移的商店?

任何想法将非常感激。

应用程序启动时没有数据指向持久性商店协调员。

看起来像选项字典的评估是好的,但在任何结果你总是设置具有相同的持久性存储URL的协调员。

同样,在迁移例程中,您正在迁移持久性存储对象,但具有相同的URL。 这是行不通的,因为这是保存实际文件的地方。 您需要本地商店和iCloud商店的不同URL,然后才能正确迁移数据,并select删除不再需要的URL(从协调器中删除商店后)。

根据您的评估结果设置协调员的url,希望您可以在应用程序启动时看到您的数据。