2014-02-27 61 views
0

我必须在名为Person和Goal的核心数据中使用NSManagedObjects。他们有多对多的关系。我有一个表视图控制器,显示与给定的Person对象关联的Goal对象。这个tableview控制器的目的是允许你点击给定目标单元格内的“加号”按钮,并将“点”从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对象的更改不是。所以,当应用程序重新启动时,Goal对象看起来没有改变。

我已经使用SQL浏览器来验证更改没有写入磁盘。如果您在关闭应用程序之前查看其他VC中的目标对象,则目标对象的更改将可见 - 它就像Goal对象的更改被写入上下文一样,但它们不会持续存在,并且仅针对特定目的。

我尝试使用XCode重新生成NSManagedObject子类,但它没有解决问题。我完全被困住了,经过七个小时的试图弄清楚,我的智慧已经结束了。

+0

显示请执行数据源委托方法。并请清楚解释您的问题。 –

回答

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 
} 

因为我的子类事情就像我做的那样,组合ler并没有抛出一个错误/警告,告诉我我基本上是通过@synthesizing重新定义(在这种情况下覆盖)moneyBalance属性。这使我的自定义方法可以工作,但是使CoreData看不到变化。

一旦我删除了@synthesize和定制的制定者,又一切工作。

1

变更保存到持久性存储:

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

创建(使用一次)后,管理您的FRC:

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

NSManagedObjectContext只是一个“暂存器”,您可以对其进行更改,操作值,插入新对象或删除旧对象,但直到保存上下文后才会完成任务,完全如Oleg Sobolev所示。保存上下文会将更改提交到持久性存储区,并且在该点不是永久性前执行的所有操作。 –

+0

我实际上尝试了modifyPointdForGoal方法内的代码 - 因此每次值增加时都会保存上下文(用于故障排除)并且它不能解决问题。另外,正如我所提到的Person对象更新,所以我期望如果上下文不保存,两个对象都不会更新 - 或者这是一个不正确的假设? –