核心数据未保存在分发版本中

Posted

技术标签:

【中文标题】核心数据未保存在分发版本中【英文标题】:Core Data not saving in distribution build 【发布时间】:2015-05-26 18:39:31 【问题描述】:

我有一个非常奇怪的问题,Core Data 在开发(调试)构建中运行良好,但在通过 TestFlight 分发的分发(发布)构建中,我的 NSManagedObjectContext 对象没有正确保存。

我观察到两个问题:

保存上下文时不会发送 NSManagedObjectContextDidSaveNotification。 数据不会在两次启动之间保持不变。

仅在分发版本中可能导致此问题的原因是什么?据我所知,配置文件不会影响 Core Data。

这是我的核心数据堆栈的两个相关函数:

- (void)initializeCoreData

    NSLog(@"%s", __FUNCTION__);

    if ([self managedObjectContext]) return;

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"XXX" withExtension:@"momd"];
    NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    NSAssert(mom, @"%@:%@ No model to generate a store from", [self class], NSStringFromSelector(_cmd));

    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
    NSAssert(coordinator, @"Failed to initialize coordinator");

    self.privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    self.privateContext.persistentStoreCoordinator = coordinator;

    self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    self.managedObjectContext.parentContext = self.privateContext;



    // Persistence store
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    options[NSMigratePersistentStoresAutomaticallyOption] = @YES;
    options[NSInferMappingModelAutomaticallyOption] = @YES;
//  options[NSSQLitePragmasOption] = @ @"journal_mode":@"DELETE" ;

    NSURL *documentsURL = [[NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    // TODO: use real store url
    NSURL *storeURL = [documentsURL URLByAppendingPathComponent:@"Data2.sqlite"];

    NSError *error = nil;
    NSAssert([coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error], @"Error initializing PSC: %@\n%@", [error localizedDescription], [error userInfo]);




- (void)save;

    if (![[self privateContext] hasChanges] && ![[self managedObjectContext] hasChanges]) return;

    [[self managedObjectContext] performBlockAndWait:^
        NSError *error = nil;

        NSAssert([[self managedObjectContext] save:&error], @"Failed to save main context: %@\n%@", [error localizedDescription], [error userInfo]);

        [[self privateContext] performBlock:^
            NSError *privateError = nil;
            NSAssert([[self privateContext] save:&privateError], @"Error saving private context: %@\n%@", [privateError localizedDescription], [privateError userInfo]);
        ];
    ];

有什么想法吗?

更新:我尝试启动调试版本并将某些内容存储在 Core Data 数据库中,它在两次启动之间保持正常,然后部署了发布版本而不删除应用程序以保持数据和数据库似乎为空,然后部署了调试版本再次和现有的数据库加载正常。因此,由于某种原因,发布版本似乎存在访问数据库文件的问题。有什么想法为什么会发生?

【问题讨论】:

这些症状表明 (a) 保存尝试实际上并没有发生,或者 (b) 保存失败但您没有记录错误。检查保存过程并为您的问题添加详细信息。 我添加了一些日志,我可以确认保存没有失败。就代码路径而言,保存通过。它只是不持久。 如果它没有持续存在,那么(a)它没有被尝试,(b)它失败了,(c)你正在以某种方式保存到另一个文件,或者(d)你正在删除文件在某个时候。 我用更新编辑了这个问题:我做了一个测试,看看发布版本是否可以访问预持久化的数据库,但不能。对此有什么想法吗? 【参考方案1】:

NSAssert 通常不会在发布版本中运行,因为NS_BLOCK_ASSERTIONS 被定义为标准 Xcode 模板的一部分。或者来自文档

重要不要在条件中调用有副作用的函数 这个宏的参数。条件参数不被评估时 断言被禁用,所以如果你调用有副作用的函数, 当您在 非调试配置。

基本上不要在 Assert 中做你关心的事情。它是一个调试测试。你真的想在这里更温柔一点,软失败。

if([[self managedObjectContext] save:&error] == NO) 
    NSLog(@"Failed to save main context: %@\n%@", [error localizedDescription], [error userInfo]);

else 
    [[self privateContext] performBlock:^
        NSError *privateError = nil;
        if([[self privateContext] save:&privateError] == NO) 
            NSLog(@"Error saving private context: %@\n%@", [privateError localizedDescription], [privateError userInfo]);
        
    ];

【讨论】:

就是这样。谢谢!

以上是关于核心数据未保存在分发版本中的主要内容,如果未能解决你的问题,请参考以下文章

核心数据,NSManagedObject 在应用版本之间发生变化

保存已编辑的核心数据实体未保存

hdfs 文件未分发

核心数据实体布尔属性未保存在表格单元格删除中

增加 Kafka 中的分区数时,消息未按 RoundRobin 顺序分发

更改未保存在核心数据模型中(例如删除对象)