Core Data 只节省了大约 50% 的时间

Posted

技术标签:

【中文标题】Core Data 只节省了大约 50% 的时间【英文标题】:Core Data only saving about 50% of the time 【发布时间】:2011-12-11 14:44:55 【问题描述】:

我刚开始使用带有 sql-lite 的 Core Data,所以我有点新。我的代码基于各种在线教程,并创建了一个 xcode 核心数据应用程序以供参考。为了它的价值,我将它集成到现有的 cocos2d 应用程序中。

一切都很顺利,直到我注意到储蓄并不总是有效。虽然上下文保存总是返回 true,但有时我在检索旧数据时会取回它。永远不会产生错误。我进行了调试,以确保我传递了正确的数据来保存,但我看不到“我做错了什么”。

这是我处理保存和检索数据的“SaveDataManager”的一部分。它是我的应用委托的实例对象。

保存功能。

- (bool) saveSongOptionData

    NSManagedObjectContext *context = ((AppDelegate*)[[UIApplication sharedApplication] delegate]).managedObjectContext;

    NSManagedObject *newData = [NSEntityDescription insertNewObjectForEntityForName:@"SongOptions" inManagedObjectContext:context];
    NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"SongOptions" inManagedObjectContext:context];

    //First check if row exists, if not create it.  If so, update that row with our new high score information.
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDesc];

    //Only should be 1 record, grab it
    [request setFetchLimit:1];
    NSManagedObject *matches = nil;
    NSError *error;
    NSArray *objects = [context executeFetchRequest:request error:&error];

    if ([objects count] == 0) //None!! Lets create one
    
        [newData setValue:[NSNumber numberWithBool:[GlobalVariables sharedInstance].background] forKey:@"background"];
        [newData setValue:[NSNumber numberWithBool:[GlobalVariables sharedInstance].random] forKey:@"random"];
        [newData setValue:[NSNumber numberWithBool:[GlobalVariables sharedInstance].vibrate] forKey:@"vibrate"];
    
    else
    
        matches = [objects objectAtIndex:0];
        [matches setValue:[NSNumber numberWithBool:[GlobalVariables sharedInstance].background] forKey:@"background"];
        [matches setValue:[NSNumber numberWithBool:[GlobalVariables sharedInstance].random] forKey:@"random"];
        [matches setValue:[NSNumber numberWithBool:[GlobalVariables sharedInstance].vibrate] forKey:@"vibrate"];
    

    [request release];
    bool success = [context save:&error];

    if (!success)
        NSLog(@"%@", error.localizedDescription);

    return success;

在我的 AppDelegate 中,我创建了我的“SaveDataManager”实例,并像在 applicationDidFinishLaunching 方法中那样将上下文传递给它:

self.dataManager = [[SavedDataManager alloc] init];
self.dataManager.managedObjectContext = self.managedObjectContext;

用于检索上下文等

#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext

    if (_managedObjectContext != nil)
        return _managedObjectContext;

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil)
    
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    
    return _managedObjectContext;


- (NSManagedObjectModel *)managedObjectModel

    if (_managedObjectModel != nil)
        return _managedObjectModel;

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TestGame" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

    if (_persistentStoreCoordinator != nil)
        return _persistentStoreCoordinator;

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TestGame.sqlite"];

    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;

我不确定这是否提供了足够的信息,但如果有人能指导我正确了解为什么会发生这种情况,我将不胜感激。

【问题讨论】:

你是从主线程保存的吗? 好问题,基本上我这样调用保存函数:AppDelegate d = (AppDelegate)[[UIApplication sharedApplication] delegate]; [d.dataManager saveSongOptionData];你认为这可能是个问题吗? 【参考方案1】:

您需要将上下文保存在applicationWillTerminate: 中,也可能保存在applicationDidEnterBackground: 中。我使用这段代码来保存这两种方法:

NSError *error;
if (managedObjectContext != nil) 

    if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) 
    
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
     

我直接从 Apple Core Data 示例应用程序中得到了这个。

【讨论】:

尝试添加这个,但仍然是相同的行为。 您可以尝试在每次保存重要信息时添加此语句。在查看您的代码之后,您对 managedObjectContext 的调用似乎很奇怪,并且可能很麻烦。你应该看看在Core Data Books. 中Core Data 是如何实现的。您还应该研究自定义托管对象模型。【参考方案2】:

解决了。真是一个简单的错误。我真的很惊讶它的工作原理。如果您在我发布的代码中注意到我使用的是“_”变量。这是因为我已经合成了变量,即“managedObjectContext = _managedObjectContext”这覆盖了我的自定义 getter。不确定它是否会对某人有所帮助,但请确保阅读合成内容,因为我很长一段时间都避免这样做:P

【讨论】:

以上是关于Core Data 只节省了大约 50% 的时间的主要内容,如果未能解决你的问题,请参考以下文章

是否可以为 Core Data 定制 SQLite 构建?

Core Data 花费了太多时间

Core Data 只保存最后一项

Core-Data 后台保存性能问题

将数据与 Core Data 同步

有两个相同模型版本时的 Core Data 迁移