核心数据对象修改的属性不会立即在tableview中更新,也不会保存

时间:2013-08-14 19:46:26

标签: objective-c core-data nsmanagedobject

此应用程序将ARC和Core Data与SQLite数据库一起使用。在OSX 10.8上使用Xcode 4.6开发。该数据库包含许多实体,其中几个实体处于父/子关系中。一切都很好,除了涉及父/子关系中两个实体的情况,它们与其他实体不同,因为它们包含数值属性,这些属性是对这两个实体的其他属性执行的数学运算的结果。

子实体包含属性A,B和C(其中C = A * B)。 父实体包含属性X(其中X =其子C的总和)。

数据在同一视图中以两个NSTableView显示。我使用绑定来填充表。当我单击一个单元格来修改B时,C应该立即在同一个表中更新,而X在另一个表中更新。当我添加或删除孩子时,X也应该立即更新。

有两个问题。

  1. 当我修改B时,C立即更新,但X不是。当我添加或删除子项时,X也不会更新。为了更新X,我需要保留记录并在表格中选择另一个(然后我可以看到先前选择的记录的X得到更新)。

  2. 退出应用程序时,C和X的修改值不会写入数据库文件中。

  3. 我的代码中遗漏了什么?这是我的托管对象类。我修改了属性和类名以使其更清晰。

    // header of parent
    
    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>
    @class Child;
    @interface Parent : NSManagedObject
    @property (nonatomic, retain) NSDecimalNumber * parent_X;
    @property (nonatomic, retain) NSSet *children;
    @end
    
    @interface Parent (CoreDataGeneratedAccessors)
    - (void)addChildrenObject:(NSManagedObject *)value;
    - (void)removeChildrenObject:(NSManagedObject *)value;
    - (void)addChildren:(NSSet *)values;
    - (void)removeChildren:(NSSet *)values;
    @end
    
    
    // implementation of parent
    
    #import "Parent.h"
    @implementation Parent
    @dynamic parent_X;
    @dynamic children;
    - (void)addChildrenObject:(NSManagedObject *)value {
        NSSet *s = [NSSet setWithObject:value];
        [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:s];
        [[self primitiveValueForKey:@"children"] addObject:value];
        [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:s];
    }
    - (void)removeChildrenObject:(NSManagedObject *)value {
        NSSet *s = [NSSet setWithObject:value];
        [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueMinusSetMutation usingObjects:s];
        [[self primitiveValueForKey:@"children"] removeObject:value];
        [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueMinusSetMutation usingObjects:s];
    }
    - (void)addChildren:(NSSet *)values {
        NSSet *s = [NSSet setWithObject:values];
        [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:s];
        [[self primitiveValueForKey:@"children"] addObject:values];
        [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:s];
    }
    - (void)removeChildren:(NSSet *)values {
        NSSet *s = [NSSet setWithObject:values];
        [self willChangeValueForKey:@"children" withSetMutation:NSKeyValueMinusSetMutation usingObjects:s];
        [[self primitiveValueForKey:@"children"] removeObject:values];
        [self didChangeValueForKey:@"children" withSetMutation:NSKeyValueMinusSetMutation usingObjects:s];
    }
    - (NSDecimalNumber *)parent_X {
        return [self valueForKeyPath:@"children.@sum.child_C"];
    }
    @end
    
    
    // header of child
    
    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>
    @class Parent;
    @interface Child : NSManagedObject
    @property (nonatomic, retain) NSDecimalNumber * child_A;
    @property (nonatomic, retain) NSDecimalNumber * child_B;
    @property (nonatomic, retain) NSDecimalNumber * child_C;
    @property (nonatomic, retain) Parent *parent;
    @end
    
    
    // implementation of child
    
    #import "Child.h"
    #import "Parent.h"
    @implementation Child
    @dynamic child_A;
    @dynamic child_B;
    @dynamic child_C;
    @dynamic parent;
    - (void)awakeFromInsert {
        [super awakeFromInsert];
        [self setValue:@50.00f forKey:@"child_A"];
        [self setValue:@1.00f forKey:@"child_B"];
    } 
    -(NSDecimalNumber *)child_C {
        return [[self child_A] decimalNumberByMultiplyingBy:[self child_B]];
    }
    @end
    

1 个答案:

答案 0 :(得分:0)

在您的代码中,您似乎在添加或删除对象后未保存到CoreData。我不确定Xcode 4.6,但在4.6.3中,Xcode自动填充以下方法:

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

你有没有它,你只是忘了打电话给它?如果您没有填充,则需要添加它以将更改保存到CoreData

或者,您只需从- (BOOL)save:(NSError **)error致电NSManagedObjectContext