更改核心数据堆栈后使用核心数据创建 SQLite 文件后未更新

Posted

技术标签:

【中文标题】更改核心数据堆栈后使用核心数据创建 SQLite 文件后未更新【英文标题】:SQLite file not updated once created with Core Data after changing Core Data Stack 【发布时间】:2016-02-04 19:26:25 【问题描述】:

我更改了现有的核心堆栈,并且我的 sqlite 文件在创建后不再更新。我可以使用核心数据保存和获取数据,但 sqlite 文件始终为空(sqlite-shm 文件被更新)。我的实施错了吗?我需要做什么才能更新我的 sqlite 文件?

//头文件

@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (readonly, strong, nonatomic) NSManagedObjectContext *masterManagedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectContext *mainManagedObjectContext;

-(NSPersistentStoreCoordinator *)persistentStoreCoordinator;
-(NSManagedObjectModel *)managedObjectModel;
-(NSManagedObjectContext *)masterManagedObjectContext;
-(NSManagedObjectContext *)mainManagedObjectContext;
-(NSManagedObjectContext *)workerManagedObjectContext;

//实现文件

@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
@synthesize masterManagedObjectContext = __masterManagedObjectContext;
@synthesize mainManagedObjectContext = __mainManagedObjectContext;



//Managed object context
-(NSManagedObjectContext *)masterManagedObjectContext
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) 
        __masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [__masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
    
    return __masterManagedObjectContext;


- (NSManagedObjectContext *)mainManagedObjectContext 
    if (__mainManagedObjectContext != nil) 
        return __mainManagedObjectContext;
    

    __mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [__mainManagedObjectContext setParentContext:self.masterManagedObjectContext];
    return __mainManagedObjectContext;


- (NSManagedObjectContext *)workerManagedObjectContext 

    NSManagedObjectContext *tempMOContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    tempMOContext.parentContext = [self mainManagedObjectContext];
    return tempMOContext;


//Save methods

- (void)saveWorkerContext:(NSManagedObjectContext *)context 
    NSError *error;
    [context save:&error];
    if (!error) 
    [self saveMainContext];
    


- (void)saveMainContext 
    [self.mainManagedObjectContext performBlock:^
        NSError *error = nil;
        [self.mainManagedObjectContext save:&error];
        if(!error)
            //Write to disk after saving on the main UI context
            [self saveMasterContext];
        
    ];


- (void)saveMasterContext 

    [self.masterManagedObjectContext performBlock:^
        NSError *error = nil;
        [self.masterManagedObjectContext save:&error];
        if(error)
            NSLog(@"CORE DATA MASTER CONTEXT ERROR : %@", error);
        
    ];


-(NSManagedObjectModel *)managedObjectModel 
    if (__managedObjectModel != nil) 
        return __managedObjectModel;
    

    NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"MyResource"
                                                       ofType:@"bundle"];

    NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
    NSString *modelPath = [bundle pathForResource:@"MyData"
                                       ofType:@"momd"];
    //NSLog(@"Bundle modelURL:%@",modelPath);
    NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
    __managedObjectModel = [[NSManagedObjectModel alloc]     initWithContentsOfURL:modelURL];
    return __managedObjectModel;



-(NSPersistentStoreCoordinator *)persistentStoreCoordinator 
    if (__persistentStoreCoordinator != nil) 
        return __persistentStoreCoordinator;
    

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyData.sqlite"];
    //NSLog(@"storeURL:%@",storeURL);
    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) 

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    

    return __persistentStoreCoordinator;


- (NSURL *)applicationDocumentsDirectory 
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

//尝试保存数据的示例

-(void)saveDictionary:(NSMutableDictionary *)myDictionary

    NSManagedObjectContext *context = [self workerManagedObjectContext];
    [context performBlockAndWait:^

        NSMutableDictionary *tmpDic = myDictionary;
        NSError *error;
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Entity"
                                              inManagedObjectContext:context];

        [fetchRequest setEntity:entity];
        NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

        Entity *myEntity;

        if ([fetchedObjects count]>0) 
            myEntity = [fetchedObjects lastObject];
        
        else
            myEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Entity" inManagedObjectContext:context];
        

        myEntity.value = tmpDic[@"value1"]!=nil?tmpDic[@"value1"]:@"nothing";


        [self saveWorkerContext:context];
    ];

【问题讨论】:

【参考方案1】:

我需要做什么才能让它工作?

但你也说过

我能够使用核心数据保存和获取数据...

这就是使用 Core Data “工作”的定义。如果这行得通,你就完成了。

SQLite shm 文件是 SQLite 日志。这是 SQLite 如何工作的实现细节。如果您有兴趣,可以阅读how SQLite manages its files,但这与您正在做的事情并不真正相关。

【讨论】:

也许我应该将我的问题从“我需要做什么才能让它发挥作用?”到“我需要做什么才能更新我的 sqlite 文件?”更清楚? 为什么要更新它?让 SQLite 像它想要的那样使用它的日志文件有什么问题?你想解决什么问题? @TomHarrington 仅用于测试例如迁移过程。我有相同的问题。我需要预先填充我的商店。【参考方案2】:

仅当您想要生成 sqlite 文件时,在添加持久存储时使用以下选项:

@NSSQLitePragmasOption: @@"journal_mode": @"DELETE"

[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil
                                                            URL:self.localStoreURL
                                                        options:@NSSQLitePragmasOption: @@"journal_mode": @"DELETE"
                                                          error:nil];

然后运行应用程序,退出,进入应用程序文件夹并在Documents 中更新您的文件。我希望这会对你有所帮助。

【讨论】:

以上是关于更改核心数据堆栈后使用核心数据创建 SQLite 文件后未更新的主要内容,如果未能解决你的问题,请参考以下文章

核心数据/SQLite 存储偶尔数据丢失

XCode4 - 在哪里寻找由核心数据创建的 sqlite 文件

从 UIManagedDocument 到普通堆栈的核心数据迁移

更改核心数据关系验证规则后保存缓慢

核心数据会自动创建 SQLite 数据库文件吗?

将核心数据实现到现有应用程序中,创建或未编写的 sqlite