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

Core Data not saving in distribution build

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

我观察到两个问题:

什么可能只在分发版本中造成这种情况?据我所知,配置文件不会影响核心数据。

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

- (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 数据库中存储一些东西,它在两次启动之间保持良好状态,然后部署了一个发布版本而不删除应用程序以保持数据和数据库似乎是空的,然后部署了一个再次调试构建,现有数据库加载正常。因此,由于某种原因,发布版本似乎在访问数据库文件时出现问题。想知道为什么会这样吗?

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

IMPORTANT Do not call functions with side effects in the condition parameter of this macro. The condition parameter is not evaluated when assertions are disabled, so if you call functions with side effects, those functions may never get called when you build the project in a non-debug configuration.

基本上不要在 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]);
        }
    }];
}