关系保存时核心数据崩溃
Posted
技术标签:
【中文标题】关系保存时核心数据崩溃【英文标题】: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' lists
repairs` 为
@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
【参考方案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 中,很多事情都发生在水下,那里的崩溃可能会使一些奇怪的碎片向上漂浮,从而掩盖真正的问题。
【讨论】:
以上是关于关系保存时核心数据崩溃的主要内容,如果未能解决你的问题,请参考以下文章