0

我面临的问题是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; 
}
4

0 回答 0