iphone - 核心数据不会持续更新数据库的属性

标签 iphone cocoa-touch ios core-data nsmanagedobject

我正在使用 NSManagedObject 的子类。实际上,它继承自一个继承自 NSManagedObject 的类的类(这应该不是问题,对吧?)。

问题

在我更改对象的属性后,该对象会在其生命周期内记住这些更改,但这些更改永远不会保存到数据库中。

我怎么知道?

我知道这是因为:

  • 当我重新启动应用程序时,我所做的更改将丢失。
  • 告诉上下文刷新对象——在我对对象进行更改并告诉上下文保存之后——将对象的值设置回我进行更改之前的原始状态。
  • 在模拟器中运行应用程序时,我可以查看 Finder 中的 sqlite 数据库文件,并且当我尝试保存上下文时,它的修改日期不会更新。

  • 什么都没有写入数据库!

    语境

    我正在使用自动生成的委托(delegate)方法来创建商店协调器和上下文。然后我按照文档中的建议将上下文传递到 View Controller 的 init 方法中。商店是 SQLite。

    我能够成功地将对象插入数据库并读取它们。我什至可以对新插入的对象进行属性更改并成功保存。当对象从数据库中拉出时,我似乎无法更新对象属性。

    该对象是通过与另一个对象的关系从商店中获取的。更改其属性后,我调用上下文的 save 方法。但是,在这样做之前,我调用了对象的 isUpdated 方法和上下文的 hasChanges 方法,两者都返回 false。因为我刚刚更改了对象的属性但尚未保存上下文,所以它们不应该返回 true 吗?

    更多

    如果我在保存上下文之前调用对象的 commitChanges 方法,但是,传入我已更改的属性的名称,我会返回正确的属性值。我不确定这意味着什么。我原以为这意味着对象的新属性值已成功保存,但显然它们没有保存。

    我知道结果对象是用上下文注册的。如果我打电话
    [[result managedObjectContext] refreshObject:result mergeChanges:YES];
    

    对象恢复到原始属性值。这意味着上下文就在那里,并且它与获取记录的上下文相同。这意味着新的属性值永远不会写入数据库。

    一些代码

    这是我正在研究所有这些东西的代码。在我的代码中还有其他地方我正在更改属性,但这些更改永远不会保存。
    - (IBAction)statusControlChanged:(UISegmentedControl *)control {
    WCAAssessmentResult *result = [self currentResult];
    
        /* printing the existing property values */
        if (![result.complete boolValue]) NSLog(@"result is in progress!");
        else if ([result.passed boolValue]) NSLog(@"result is passed!");
        else NSLog(@"result is not passed!");
    
        /* changing the property values */
        switch (control.selectedSegmentIndex) {
            case 0:
                NSLog(@"setting incomplete");
                result.complete = [NSNumber numberWithBool:NO];
                break;
            case 1:
                NSLog(@"setting passed");
                result.passed = [NSNumber numberWithBool:YES];
                result.complete = [NSNumber numberWithBool:YES];
                break;
            case 2:
                NSLog(@"setting failed");
                result.passed = [NSNumber numberWithBool:NO];
                result.complete = [NSNumber numberWithBool:YES];
                break;
            default:
                break;
        }
    
        /* this method always returns an empty dictionary */
        NSLog(@"%@", [result changedValues]);
    
        /* this method returns the values that I just set */
        NSLog(@"%@", [result committedValuesForKeys:[NSArray arrayWithObjects:@"complete", @"passed", nil]]);
    
        /* isUpdated returns false */
        if (![result isUpdated]) {
            NSLog(@"result is not updated?! WTF!?!?");
        }
    
        /* hasChanges returns false */
        if (![[result managedObjectContext] hasChanges]) {
            NSLog(@"context has no changes!? WTF!?!?");
        }
    
        /* saving the context produces no error */
        NSError *error = nil;
        if (![[result managedObjectContext] save:&error]) {
            NSLog(@"save failed");
            NSLog(@"%@",[error description]);
        }
    }
    

    一转

    如果我通过在上下文中插入新记录来创建新的结果对象,我可以设置该对象的属性并成功保存它们。在上面的代码中,我从另一个对象中获取对象作为多对多关联的成员。这是线索吗?

    我正在为此烦恼。这里到底出了什么问题?

    什么不是问题
  • 我已经记录了对象的类,它确实是正确的类
  • 我已经确保我保存的 managedObjectContext 与对象的上下文相同
  • 我没有对我的托管对象类的自动生成的 setter/getter 方法进行任何更改
  • 我尝试使用 setValue:forKey: 方法而不是对象的属性
  • 我用过 -com.apple.CoreData.SQLDebug 1记录 Core Data SQL 的参数,当我更新和保存对象的属性时没有记录 SQL
  • 最佳答案

    我不太明白你的说法

    WCAAssessmentResult *result = [self currentResult];
    

    事实上,如果您从一个对象访问一对多关系,您应该返回一个集合,而不是一个对象。无论如何,没有看到代码就很难说。您遇到的问题可能存在也可能不存在。

    我宁愿在您的代码中使用类似于以下代码段的内容来访问属于多对多关系的对象。我假设 yourObject是您用来访问 WCAAssessmentResult 的对象多对多关系中的对象,我称之为 results .
    NSMutableSet *resultObjects = [yourObject mutableSetValueForKey:@"results"];
    NSPredicate *predicate = ...
    [resultObjects filterUsingPredicate:predicate];
    
    for(WCAAssessmentResult *result in resultObjects){
    
       // modify as needed the current result object
    
    }
    
    NSError *error = nil;
    if (![managedObjectContext save:&error]) {
            NSLog(@"save failed");
            NSLog(@"%@",[error description]);
    }
    

    您是否验证过用于保存对象的 managedObjectContext 是否有效(非 nil)?

    关于iphone - 核心数据不会持续更新数据库的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5628996/

    相关文章:

    ios - 在闭包中管理封装数据

    iphone - 如何在应用更新下载后再次调用 didFinishLaunchingWithOptions

    cocoa-touch - 使用 beginAnimations 后如何停止动画?

    iphone - iOS 中 SQLite 中的巨大静态数据 - iPhone

    ios - 如何在 UITextView 中的空格之间获取单词?

    iphone - 是否有 iOS 库可以帮助我检测更高级别的加速计手势?

    ios - 我怎么知道我的应用程序在后台运行?

    objective-c - UIPickerView 中不同大小的多个组件/列

    ios - 应用程序将终止 : not being called

    ios - EXC_BAD_INSTRUCTION 尝试从 Parse 获取图像时