对Core Data对象的更改不会持久化

时间:2014-02-27 23:41:53

标签: ios objective-c uitableview core-data

我必须在名为Person and Goal的核心数据中使用NSManagedObjects。他们有多对多的关系。我有一个表视图控制器,显示与给定的Person对象关联的Goal对象。此tableview控制器的目的是允许您点击给定Goal单元格内的“加号”按钮,并将“点”从Person对象传输到Goal对象。

用于执行此操作的获取请求是:

NSManagedObjectContext *context = self.context;

if (self.selectedItemID) {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Goal"];
request.sortDescriptors = [NSArray arrayWithObjects:
                               [NSSortDescriptor sortDescriptorWithKey:@"name"
                                                             ascending:YES],
                               nil];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self IN %@) AND (completed     == %@)",
                      person.goals,
                      [NSNumber numberWithBool:NO]];

if (predicate) [request setPredicate:predicate];

//Note: |self.frc| is defined in the super class
self.frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                   managedObjectContext:context
                                                     sectionNameKeyPath:nil
                                                              cacheName:nil];
self.frc.delegate = self;

这是每个目标单元格中​​“加号”按钮调用的方法:

- (IBAction)modifyPointsForGoal:(UIButton *)sender {

//Get a reference to the |Goal| object for the button's cell.  The view hierarchy may not be fixed,
//so traverse up the view hierarchy until a UITableViewCell is found and get its NSIndexPath

UIView *view = sender;
while (![view isKindOfClass:[GoalForPersonCell class]]) view = view.superview;
GoalForPersonCell *cell = (GoalForPersonCell *)view;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

//Get reference to |Goal| and |Person| object
Goal *cellsGoal = (Goal *)[self.frc objectAtIndexPath:indexPath];
NSManagedObjectID *cellsGoalObjectID = cellsGoal.objectID;
Goal *goal = (Goal *)[self.context existingObjectWithID:cellsGoalObjectID
                                                    error:nil];

Person *person = self.person;


//Using the button tag numbers, increment/decrement values as needed
gFPVCSenderButtonType buttonType = (int)sender.tag;
switch (buttonType) {
    case giveAdd:
        [goal incrementValueBalanceWithDefaults];
        break;

    case giveSubtract:
        [goal decrementValueBalanceWithDefaults];
        break;

    case bankAdd:
        // decrementBalanceForGoalType returns FALSE if there are insufficient funds
        if ([person decrementBalanceUsingGoal:goal])
            [goal incrementValueBalanceWithDefaults];
        break;

    case bankSubtract:
        // decrementValueBalance returns FALSE if there are insufficient funds
        if ([goal decrementValueBalanceWithDefaults])
            [person incrementBalanceUsingGoal:goal];
        break;

    default:
        break;
}

}

每个单元格中的按钮按预期工作 - 值从Person对象获取并提供给单元格表示的Goal对象。我遇到的问题是对Person对象的更改被写入持久性存储,但对Goal对象的更改则不会。因此,当重新启动应用程序时,目标对象似乎没有变化。

我使用SQL浏览器来验证更改是否未写入磁盘。如果您在关闭应用程序之前查看其他VC中的Goal对象,则可以看到对象对象的更改 - 就好像对象的更改被写入上下文一样,但是它们不再持续存在,并且仅针对特定对象对象

我尝试使用XCode重新生成NSManagedObject子类,但它没有解决问题。我完全被难倒了,经过七个小时的努力弄清楚,我已经知道了。

2 个答案:

答案 0 :(得分:1)

将更改保存到持久存储中:

NSError *err= nil;
[managedObjectContext save:&err];

创建后使用FRC(使用一次):

    [FRC setAutomaticallyPreparesContent:<#(BOOL)#>];
    [RFC setAutomaticallyRearrangesObjects:<#(BOOL)#>];

答案 1 :(得分:0)

最终问题出在我的实体的NSManagedObject子类上。

我没有将自定义方法添加到Xcode从我的数据模型创建的NSManaged子类中,而是使用了一种技术,而我使用XCode创建了NSManagedObject子类,然后再次将其子类化以添加我的自定义方法。我这样做是因为它允许您更改实体并使用XCode重新创建NSManagedObject子类,而不会破坏您编写的所有自定义方法。

这也让我做了一件坏事:

_Goal.m

#import "_Goal.h"
@implementation _Goal

@dynamic moneyBalance;
@end

Goal.h

#import "Goal.h"
@end

Goal.m

@synthesize moneyBalance = _moneyBalance

-(NSManagedObject *)setMoneyBalance {
//Custom setter code for boundry checking
}

因为我按照我的方式对事物进行了子类化,所以编译器没有抛出错误/警告告诉我,我基本上是通过@synthesizing重新定义(在这种情况下覆盖)moneyBalance属性。这允许我的自定义方法工作,但使CoreData不可见更改。

一旦我删除了@synthesize和自定义设置器,一切都恢复了。