简体   繁体   English

对核心数据对象的更改未持久

[英]Changes to Core Data object not persisting

I have to NSManagedObjects in core data called Person and Goal. 我必须在名为Person和Goal的核心数据中使用NSManagedObjects。 They have a many-to-many relationship. 他们有多对多的关系。 I have a table view controller that shows the Goal objects associated with a given Person object. 我有一个表视图控制器,该控制器显示与给定Person对象关联的Goal对象。 The purpose of this tableview controller is to allow you to tap a "plus" button inside a given Goal cell and have "points" transferred from the Person object to the Goal object. 这个tableview控制器的目的是允许您点击给定目标单元格内的“加号”按钮,并将“点”从“人”对象转移到“目标”对象。

The fetch request used to do this is: 用于执行此操作的获取请求是:

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;

This is the method called by the "Plus" button in each Goal cell: 这是每个目标单元格中​​“加号”按钮所调用的方法:

- (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;
}

} }

The buttons in each cell work as expected - values are taken from the Person object and given to the Goal object represented by the cell. 每个单元格中的按钮均按预期工作-值取自Person对象,并提供给该单元格表示的Goal对象。 The problem I'm having is that changes to the Person object are written to the persistent store, but changes to the Goal object are not. 我遇到的问题是对Person对象的更改被写入了持久性存储,而对Goal对象的更改却没有。 So, when the app is restarted the Goal object(s) appear to be unchanged. 因此,当应用重新启动时,目标对象似乎没有改变。

I've used a SQL browser to verify the changes aren't being written to disk. 我已经使用SQL浏览器来验证更改是否未写入磁盘。 The changes to the Goal objects are visible if you view the Goal object in other VCs BEFORE closing the app - its as though the changes to the Goal object are written to the context, but again they don't persist, and only for that specific object. 如果您在关闭应用程序之前在其他VC中查看目标对象,则对目标对象的更改是可见的-好像对目标对象的更改已写入到上下文中,但它们不会持久存在,并且仅针对该特定对象宾语。

I tried using XCode to regenerate the NSManagedObject subclasses and it didn't resolve the issue. 我尝试使用XCode重新生成NSManagedObject子类,但无法解决问题。 I'm completely stumped, and after seven hours of trying to figure it out I'm at my wits end. 我完全陷入了困境,经过七个小时的努力弄清楚,我才机智。

Save changes into persistent store: 将更改保存到持久性存储中:

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

Manage your FRC after creating (use once): 创建后管理您的FRC(使用一次):

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

It ends up the issue was with my NSManagedObject subclass for the entity. 最终问题出在我的实体的NSManagedObject子类中。

Rather than add custom methods to the NSManaged sublass created by Xcode from my data model, I used a technique whereas I created the NSManagedObject subclass using XCode and then subclassed it again to add my custom methods. 我没有使用自定义方法向Xcode从数据模型创建的NSManaged子类中添加自定义方法,而是使用了一种技术,而是使用XCode创建了NSManagedObject子类,然后再次对其进行子类化以添加我的自定义方法。 I did this because it allows you to change the entity and re-create the NSManagedObject subclass using XCode without clobbering all the custom methods you wrote. 我这样做是因为它允许您更改实体并使用XCode重新创建NSManagedObject子类,而不会破坏您编写的所有自定义方法。

It also allowed me to do something bad: 这也让我做不好的事情:

_Goal.m _Goal.m

#import "_Goal.h"
@implementation _Goal

@dynamic moneyBalance;
@end

Goal.h Goal.h

#import "Goal.h"
@end

Goal.m Goal.m

@synthesize moneyBalance = _moneyBalance

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

Because I subclassed things the way I did, the compiler didn't throw an error/warning telling me that I was essentially redefining (in this case overriding) the moneyBalance property by @synthesizing it. 因为我按照自己的方式对事物进行了子类化,所以编译器没有引发错误/警告,告诉我我实际上是通过@synthesize来重新定义moneyBalance属性(在这种情况下,它是重写)。 This allowed my custom methods to work, but made changes invisible to CoreData. 这允许我的自定义方法起作用,但使CoreData看不到更改。

Once I removed the @synthesize and custom setters, everything worked again. 删除@synthesize和自定义设置器后,所有操作又恢复了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM