我有一個很難解決的問題。我有這種情況:Hard CoreData + iCloud場景
我的應用程序使用CoreData來存儲對象,我想實現設備之間的iCloud同步...和我的應用程序需要初始填充數據庫。
第一次啓動我的應用程序時,它會將我的數據庫填充到雲上,並將某些db字段標記爲「databaseInstalled」。這些字段也在雲中同步。
現在,當其他設備啓動應用程序的第一次,我希望能檢索字段「databaseInstalled」,以檢查是否注入與否的一些數據,但它是錯的......
如果databaseInstalled是假的,我們注入數據,如果databaseInstalled是真的,我們等待iCloud同步。
的問題是,我找回persistentStoreCoordinator異步地,因爲我不想阻止正在等待從iCloud中下載數據應用...
那麼如何才能知道一個先驗的,如果我需要填充數據庫還是已經填充到另一臺設備上,我只需從iCloud下載一個已安裝的設備?
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if((__persistentStoreCoordinator != nil)) {
return __persistentStoreCoordinator;
}
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator;
// Set up iCloud in another thread:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// ** Note: if you adapt this code for your own use, you MUST change this variable:
NSString *iCloudEnabledAppID = @"this is a secret!";
// ** Note: if you adapt this code for your own use, you should change this variable:
NSString *dataFileName = @"you do not have to know.sqlite";
// ** Note: For basic usage you shouldn't need to change anything else
NSString *iCloudDataDirectoryName = @"Data.nosync";
NSString *iCloudLogsDirectoryName = @"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloud) {
NSLog(@"iCloud is working");
NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];
NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
NSLog(@"dataFileName = %@", dataFileName);
NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
NSLog(@"iCloud = %@", iCloud);
NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);
// da rimuovere
//[fileManager removeItemAtURL:iCloudLogsPath error:nil];
#warning to remove
if([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
NSError *fileSystemError;
[fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
withIntermediateDirectories:YES
attributes:nil
error:&fileSystemError];
if(fileSystemError != nil) {
NSLog(@"Error creating database directory %@", fileSystemError);
}
}
NSString *iCloudData = [[[iCloud path]
stringByAppendingPathComponent:iCloudDataDirectoryName]
stringByAppendingPathComponent:dataFileName];
//[fileManager removeItemAtPath:iCloudData error:nil];
#warning to remove
NSLog(@"iCloudData = %@", iCloudData);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey];
[options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey];
[psc lock];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:[NSURL fileURLWithPath:iCloudData]
options:options
error:nil];
[psc unlock];
}
else {
NSLog(@"iCloud is NOT working - using a local store");
NSLog(@"Local store: %@", localStore.path);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[psc lock];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:localStore
options:options
error:nil];
[psc unlock];
}
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"iCloud routine completed.");
Setup *install = [[Setup alloc] init];
if([install shouldMigrate]) {
HUD = [[MBProgressHUD alloc] initWithView:self.window.rootViewController.view];
HUD.delegate = self;
HUD.labelText = NSLocalizedString(@"Sincronizzazione del database", nil);
[self.window.rootViewController.view addSubview:HUD];
[HUD showWhileExecuting:@selector(installDatabase) onTarget:install withObject:nil animated:YES];
}
else {
[[NSNotificationCenter defaultCenter] postNotificationName:@"setupCompleted" object:self];
}
//[[NSNotificationCenter defaultCenter] postNotificationName:@"icloudCompleted" object:self userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"setupCompleted" object:self];
});
});
return __persistentStoreCoordinator;
}
數據從預填充數據庫中的量是很大的,從1K到4K的對象(記錄)。第二個選擇是它如何工作,但我有另一個問題...該應用程序是第一次注入對象來填充數據庫,同時它正在合併數據與iCloud ...並且我有一個異常(集合被靜音)在我的NSFetchedResultsController ...仍然令人不安... – Progeny
我忘記了...選項2的主要問題是,我的數據庫是重複的,因爲兩個設備在iCloud上同步本地數據庫...合併本地數據庫從iCloud不刪除現有的記錄,但重複它的! – Progeny
您回答基於文檔的應用程序而不是CoreData + iCloud。有沒有簡單的方法來解決預填充數據庫方案。至少我還沒有找到一個。主要的問題是,一旦用數據預填充數據庫,就會出現重複。 ObjectId將會不同。 –