关系保存时核心数据崩溃

时间:2014-08-06 20:10:03

标签: objective-c macos core-data nsfetchrequest

我有一个核心数据应用,我试图将新对象添加到具有关系的实体。访问导致应用程序崩溃的关系实体出现问题保存

添加发生在工作表内。

保存操作:

-(IBAction)addNewRepair:(id)sender {
    NSError *error = nil;
    NSArray *fetchedObjects;
    NSManagedObjectContext *context = [[NSApp delegate] managedObjectContext];

    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Equipment"  inManagedObjectContext:context];

    [fetch setEntity:entityDescription];

    [fetch setPredicate:[NSPredicate predicateWithFormat:@"(serial like %@)",[[serialPopUp selectedItem] title]]];

    fetchedObjects = [context executeFetchRequest:fetch error:&error];

    Equipment *equipmentObject = [fetchedObjects objectAtIndex:0];

    Repairs *newRepair = (Repairs*)[NSEntityDescription
                                    insertNewObjectForEntityForName:@"Repairs"
                                    inManagedObjectContext:[[NSApp delegate] managedObjectContext]];

    [newRepair setValue:invoiceNumberTextFeild.stringValue forKeyPath:@"invoiceNumber"];
    [newRepair setValue:warrentyTextField.stringValue forKeyPath:@"warrantyDate"];
    [newRepair setValue:repairReasonTextField.stringValue forKeyPath:@"repairDetails"];
    [newRepair setValue:serviceProvidedTextField.stringValue forKeyPath:@"serviceSummary"];
    [newRepair setValue:serviceDateTextField.stringValue forKeyPath:@"repairDate"];
    [equipmentObject addRepairsObject:(Repairs *)newRepair];

    if (![[[NSApp delegate] managedObjectContext]  save:&error])
    {
        NSLog(@"couldn't save: %@", [error localizedDescription]);
    }

    NSLog((@"Repair Successfully added"));
    [NSApp endSheet:self.sheet];
    [self.sheet close];
}

获取方法:

-(void)fetchItems {

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Equipment"];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Equipment" inManagedObjectContext:[[NSApp delegate] managedObjectContext]];

    fetchRequest.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:@"item"]];

    fetchRequest.entity = entity;
    fetchRequest.resultType = NSDictionaryResultType;
    [fetchRequest setReturnsDistinctResults:YES];

    itemDictionaries = [[[NSApp delegate] managedObjectContext] executeFetchRequest:fetchRequest error:nil];

    NSLog(@"item: %@", itemDictionaries);

    [nameController setContent:itemDictionaries];
    self.itemSelection = [itemDictionaries firstObject];

    self.predicate  = [NSPredicate predicateWithFormat:@"item == %@", [[nameController selection] valueForKeyPath:@"item"]];
}

这种方法可能出现什么问题?

我的equipment.h文件实现了一个自定义访问器:

- (void)addRepairsObject:(Repairs *)value;
{
    [self willChangeValueForKey:@"Repairs"];
    [self setPrimitiveValue:value forKey: @"Repairs"];
    [self didChangeValueForKey:@"Repairs"];
}

我得到的错误是:

  

2014-08-06 12:41:50.805 CNSplitView_Example [64803:4407] - [设备   copyWithZone:]:无法识别的选择器发送到实例0x6080002c0a10

即使equipment.h' lists修复为

@property (nonatomic, retain) NSSet *repairs;

有人能指出我正确的方向吗?从我正在阅读的内容来看,这是一个常见问题(几乎总是在IOS上,而不是OS X应用程序),但没有广泛记录的解决方案。

我也试过这个:

NSMutableSet *newRepairObject = [NSMutableSet setWithObject:equipmentObject];
    equipmentObject.repairs = newRepairObject;

同样的错误。

编辑:

发现NSManagedObjects不符合NSCopying协议。 (那么为什么错误在该实体上产生copyWithZone?)

1 个答案:

答案 0 :(得分:0)

问题在于addRepairsObject:方法。您正在使用属性访问器setPrimitiveValue:当您应该使用一对多关系访问器时。核心数据编程指南在Managed Object Accessor Methods

部分提供了一个示例
@dynamic employees;


- (void)addEmployeesObject:(Employee *)value {

    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];

    [self willChangeValueForKey:@"employees"
          withSetMutation:NSKeyValueUnionSetMutation
          usingObjects:changedObjects];
    [[self primitiveEmployees] addObject:value];
    [self didChangeValueForKey:@"employees"
          withSetMutation:NSKeyValueUnionSetMutation
          usingObjects:changedObjects];
}

替换“员工”的'维修',你应该没事。 NSCopying错误是红色鲱鱼:在核心数据中,相当多的东西发生在水下,一次崩溃可能会发送一些奇怪的碎片向上浮动,掩盖了真正的问题。