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

Cha*_*zak 5 iphone cocoa-touch core-data nsmanagedobject ios

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

问题

在对对象的属性进行更改后,对象会记住其生命周期的更改,但更改永远不会保存到数据库中.

我怎么知道这个?

我知道这是因为:

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

没有任何东西写入数据库!

上下文

我正在使用自动生成的委托方法来创建商店协调器和上下文.然后我按照文档中的建议将上下文传递给它们的init方法中的视图控制器.这家商店是SQLite.

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

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

更多

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

我知道结果对象是在上下文中注册的.如果我打电话

[[result managedObjectContext] refreshObject:result mergeChanges:YES];
Run Code Online (Sandbox Code Playgroud)

对象恢复为原始属性值.这意味着上下文存在,并且它是从中获取记录的相同上下文.这意味着新属性值永远不会写入数据库.

一些代码

这是我正在探讨所有这些事情的代码.我的代码中有其他地方我正在进行属性更改,但更改永远不会保存.

- (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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

扭曲

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

我正在撕裂我的头发.这到底怎么可能出错?

什么不是问题

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

Mas*_*aro 3

我不太明白你的说法

WCAAssessmentResult *result = [self currentResult];
Run Code Online (Sandbox Code Playgroud)

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

我宁愿期望在您的代码中使用类似以下代码片段的内容来访问属于一对多关系的对象。我假设这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]);
}
Run Code Online (Sandbox Code Playgroud)

您是否验证用于保存对象的 ManagedObjectContext 是否有效(不是 nil)?