【发布时间】:2011-04-12 00:15:40
【问题描述】:
我正在使用 NSManagedObject 的子类。实际上,它继承自一个类,该类继承自一个本身继承自 NSManagedObject 的类(这应该不是问题,对吧?)。
问题
在我对对象的属性进行更改后,对象会在其生命周期内记住更改,但不会将更改保存到数据库中。
我怎么知道的?
我知道这是因为:
- 当我重新启动应用程序时,我所做的更改会丢失。
- 告诉上下文刷新对象——在我对对象进行更改并告诉上下文保存之后——将对象的值设置回我进行更改之前的原始状态。
- 在模拟器中运行应用程序时,我可以在 Finder 中查看 sqlite 数据库文件,当我尝试保存上下文时,它的修改日期没有更新。
没有任何东西被写入数据库!
上下文
我正在使用自动生成的委托方法来创建商店协调器和上下文。然后,按照文档中的建议,我在它们的 init 方法中将上下文传递给视图控制器。商店是 SQLite。
我能够成功地将对象插入数据库并读取它们。我什至可以对新插入的对象进行属性更改并成功保存。当对象从数据库中拉出时,我似乎无法更新对象属性。
对象是通过与另一个对象的关系从存储中获取的。在对其属性进行更改后,我调用上下文的保存方法。但是,在这样做之前,我调用了对象的 isUpdated 方法和上下文的 hasChanges 方法,两者都返回 false。由于我刚刚更改了对象的属性但没有保存上下文,它们不应该返回 true 吗?
更多
如果我在保存上下文之前调用对象的committedChanges 方法,但是,传入我已更改的属性的名称,我会取回属性的正确值。我不确定这意味着什么。我本来以为这意味着对象的新属性值已经成功保存,但显然它们没有保存。
我知道结果对象是在上下文中注册的。如果我打电话
[[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
【问题讨论】:
-
常见问题?从来没有听说过。在里面放一个
NSAssert(result, @"TF!"); -
同意 -
resultnil 首先?也将一个 NSError 对象传递给save:并询问其结果? -
更新了问题。错误对象为空。
-
它应该为自己感到羞耻。
-
您是否继承了
NSManagedObject?如果是这样,您可以发布该代码吗?
标签: iphone cocoa-touch ios core-data nsmanagedobject