我面临的问题是NSPersistentStoreCoordinator 没有持久存储。它无法执行保存操作。
在我的应用程序中,当应用程序启动并在后台使用单独的 manageObjectContext 进行联系人同步过程并在后台成功地进行联系人同步时。
我已经为 iCloud 配置设置好了。
我的应用程序中有一个选项,其中设置了 iCloud ON/OFF,因此每当 iCloud 打开并从设备的后台删除应用程序并重新启动时,应用程序由于 persistentStore 而崩溃,同时将 manageObjectContext 保存在核心数据中。
请给我建议或任何想法。
感谢您提前提供帮助。
请参阅我的以下 iCloud 代码
PFCoreDataController.h
@interface PFCoreDataController : NSObject
{
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
}
@property(nonatomic, retain, readonly)NSManagedObjectModel *managedObjectModel;
@property(nonatomic, retain, readonly)NSManagedObjectContext *managedObjectContext;
@property(nonatomic, retain)NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property(nonatomic, readonly)NSString *applicationDocumentsDirectory;
@property(nonatomic, retain)NSArray *settingsArray;
@property(nonatomic, readwrite)int iCloudValue;
@property(nonatomic, retain)NSManagedObjectContext *managedObjectContextBack;
@property(nonatomic, retain)NSManagedObjectContext *managedObjectContextBackTEST;
@property(nonatomic, retain)NSMutableDictionary *keycontactDict;
+ (PFCoreDataController *)sharedCoreDataController;
PFCoreDataController.m
+ (PFCoreDataController *)sharedCoreDataController
{
if(coreDataController == nil)
{
coreDataController = [[PFCoreDataController alloc]init];
}
return coreDataController;
}
// For iCloud use below section
- (NSManagedObjectContext *) managedObjectContext
{
if (managedObjectContext != nil)
{
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
self.keycontactDict = [[NSMutableDictionary alloc] init];
BOOL isiCloudValue = [[NSUserDefaults standardUserDefaults] boolForKey:iCLOUD_VALUE];
if (isiCloudValue)
{
DLog(@"iCloud enabled");
float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
DLog(@"into Version %f",ver);
if (ver >= 5.0)
{
NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[moc performBlockAndWait:^{
[moc setPersistentStoreCoordinator: coordinator];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeChangesFrom_iCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator];
}];
managedObjectContext = moc;
}
}
else
{
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
self.managedObjectContextBack = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[self.managedObjectContextBack setUndoManager:nil];
[self.managedObjectContextBack setParentContext:managedObjectContext];
self.managedObjectContextBackTEST = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[self.managedObjectContextBackTEST setUndoManager:nil];
[self.managedObjectContextBackTEST setParentContext:managedObjectContext];
// self.managedObjectContextUI = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
// [self.managedObjectContextUI setUndoManager:nil];
// [self.managedObjectContextUI setParentContext:managedObjectContext];
//
// self.managedObjectContextBack = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
// [self.managedObjectContextBack setUndoManager:nil];
// [self.managedObjectContextBack setParentContext:managedObjectContext];
}
}
return managedObjectContext;
}
// For iCloud use below section
- (NSManagedObjectModel *)managedObjectModel
{
if (managedObjectModel != nil) {
return managedObjectModel;
}
BOOL isiCloudValue = [[NSUserDefaults standardUserDefaults] boolForKey:iCLOUD_VALUE];
if (isiCloudValue)
{
DLog(@"iCloud enabled");
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"PurpleFolder" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
else{
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
}
return managedObjectModel;
}
// For iCloud use below section
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator != nil)
{
return persistentStoreCoordinator;
}
NSURL *storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent:SQLITE_FILE_NAME]];
BOOL isiCloudValue = [[NSUserDefaults standardUserDefaults] boolForKey:iCLOUD_VALUE];
self.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (isiCloudValue)
{
DLog(@"iCloud enabled");
NSPersistentStoreCoordinator* psc = self.persistentStoreCoordinator;
float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
if (ver >= 5.0)
{
DLog(@"into Version %f",ver);
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 = @"NB8QU2BXAM.com.siliconithub.icloudtest";
// ** Note: if you adapt this code for your own use, you should change this variable:
NSString *dataFileName = @"iCloud.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 *urlFromAppDocDirectory = [NSURL URLWithString:[self applicationDocumentsDirectory]];
// NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
NSURL *localStore = [urlFromAppDocDirectory URLByAppendingPathComponent:dataFileName];
NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloud) {
DLog(@"iCloud is working");
NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];
DLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
DLog(@"dataFileName = %@", dataFileName);
DLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
DLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
DLog(@"iCloud = %@", iCloud);
DLog(@"iCloudLogsPath = %@", iCloudLogsPath);
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) {
DLog(@"Error creating database directory %@", fileSystemError);
}
}
NSString *iCloudData = [[[iCloud path]
stringByAppendingPathComponent:iCloudDataDirectoryName]
stringByAppendingPathComponent:dataFileName];
DLog(@"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 {
DLog(@"iCloud is NOT working - using a local store");
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(), ^{
DLog(@"into dispatech");
NSUserDefaults *stdef = [NSUserDefaults standardUserDefaults];
if ([stdef integerForKey:@"iPhoneQuoteiCloudAutoPost"] == 1)
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"SomethingChanged" object:self userInfo:nil];
}
});
});
}
else
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
NSError *error = nil;
if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
DLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
else
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
DLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
return self.persistentStoreCoordinator;
}
// Returns the path to the application's documents directory.
- (NSString *)applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
- (BOOL)addDefalultValuesToSettings
{
BOOL success = YES;
NSError *error;
Settings *defaultSettings = [NSEntityDescription insertNewObjectForEntityForName:ENTITY_SETTINGS inManagedObjectContext:self.managedObjectContext];
defaultSettings.setCalendar=[NSNumber numberWithInt:0];
defaultSettings.addActionsToNotes=[NSNumber numberWithInt:0];
defaultSettings.addTimeStampToNote=[NSNumber numberWithInt:0];
**if (![self.managedObjectContext save:&error])**
{
DLog(@"Failed to save addDefalultValuesToSettings in dB: %@", [error localizedDescription]);
success = NO;
}
return success;
}