【问题标题】:Core Data crash on relationship save关系保存时核心数据崩溃
【发布时间】:2014-08-06 20:10:02
【问题描述】:

我有一个核心数据应用程序,我正在尝试将新对象添加到具有关系的实体中。访问导致应用在保存

时崩溃的关系实体出现问题

添加发生在工作表中。

保存动作:

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

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

我的设备.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' listsrepairs` 为

@property (nonatomic, retain) NSSet *repairs;

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

我也试过这个:

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

同样的错误。

编辑:

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

【问题讨论】:

  • Equipment类是否采用NSCopying协议?该错误消息向我表明该应用程序期望它。
  • 如果我尝试实现 nscopying,我仍然会收到相同的错误:“无法识别的选择器发送到实例 0x6000002bb660 with userInfo (null)”
  • 另外,根据我的阅读,NSManagedObjects 不符合 NSCopying anyuway

标签: objective-c macos core-data nsfetchrequest


【解决方案1】:

问题在于 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];
}

用“repairs”代替“employees”,应该没问题。 NSCopying 错误是红鲱鱼:在 Core Data 中,很多事情都发生在水下,那里的崩溃可能会使一些奇怪的碎片向上漂浮,从而掩盖真正的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多