如何解决错误:实体GroceryItems不是键值“hasLocations”的键值编码兼容

时间:2013-01-23 12:09:19

标签: core-data crash entity-relationship

以下是我可以想到的所有内容,以尝试识别错误的来源。当然,我会提供任何其他可能有用的信息。在此先感谢您的帮助。

我是Core Data的新手,我有一个名为GroceryItem的实体。它有一个名为hasLocations的多对多关系,我试图用以下代码查询:

itemObject = (GroceryItem *)[GroceryItem itemNameToObject:itemName];

if (itemObject != nil)
{
    NSLog(@"%@", [NSString stringWithFormat:@"initAndFillItemLocationsTable got an item named %@", itemObject.name]);
}

if (itemLocations != nil)
{
    [itemLocations removeAllObjects];
}

if (itemObject != nil)
{
    NSLog(@"Before mutable set assignment");

    NSMutableSet *mutableLocationsSet = [itemObject mutableSetValueForKeyPath:@"hasLocations"];

我在输出中看到“Before mutable set assignment”消息,然后是

2013-01-23 03:27:14.898 Grocery Manager [6431:11603] initAndFillItemLocationsTable有一个名为Cream Cheese的商品 2013-01-23 03:27:14.899 Grocery Manager [6431:11603]在可变集合作业之前 2013-01-23 03:27:14.901 Grocery Manager [6431:11603] *由于未捕获的异常'NSUnknownKeyException'终止应用程序,原因:'[valueForUndefinedKey:]:实体GroceryItems不符合键值编码关键词“hasLocations”。' * 第一次抛出调用堆栈: (0x15eb012 0x1410e7e 0x1673fb1 0x11c304 0xe298db 0xb8374 0xe298db 0xec3180 0xec31de 0x17450 0xaa5c 0x439817 0x439882 0x439b2a 0x450ef5 0x450fdb 0x451286 0x451381 0x451eab 0x4524a3 0x452098 0x7adda3 0x79fad9 0x79fb54 0x407899 0x407b3d 0xe0ee83 0x15aa376 0x15a9e06 0x1591a82 0x1590f44 0x1590e1b 0x24377e3 0x2437668 0x35865c 0x27bd 0x26e5) libc ++ abi.dylib:terminate调用抛出异常

GroceryItem类定义的内容是:

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>


@interface GroceryItem : NSManagedObject

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSSet *hasLocations;
@property (nonatomic, retain) NSSet *containedInIngredients;

@end

@interface GroceryItem (CoreDataGeneratedAccessors)

- (void)addHasLocationsObject:(NSManagedObject *)value;
- (void)removeHasLocationsObject:(NSManagedObject *)value;
- (void)addHasLocations:(NSSet *)values;
- (void)removeHasLocations:(NSSet *)values;

- (void)addContainedInIngredientsObject:(NSManagedObject *)value;
- (void)removeContainedInIngredientsObject:(NSManagedObject *)value;
- (void)addContainedInIngredients:(NSSet *)values;
- (void)removeContainedInIngredients:(NSSet *)values;

+(GroceryItem *)itemNameToObject:(NSString *)itemName;

我已在数据库编辑器中验证了GroceryItem类已分配给实体GroceryItem。

我阅读了键值编码编程指南并在GroceryItem.m中实现了以下代码:

- (void)addHasLocationsObject:(NSManagedObject *)value
{
    [self.hasLocations setByAddingObject:value];
}

- (void)removeHasLocationsObject:(NSManagedObject *)value
{
    NSMutableSet *mutable = [NSMutableSet setWithSet:self.hasLocations];

    [mutable removeObject:value];

    self.hasLocations = mutable;
}

- (void)addHasLocations:(NSSet *)values
{
    [self.hasLocations setByAddingObjectsFromSet:values];
}

- (void)removeHasLocations:(NSSet *)values
{
    NSMutableSet *mutable = [NSMutableSet setWithSet:self.hasLocations];

    for (id obj in [mutable allObjects])
    {
        if ([values containsObject:obj])
        {
            [mutable removeObject: obj];
        }
    }
    self.hasLocations = mutable;
}

- (NSUInteger)countOfHasLocations
{     
    return [self.hasLocations count];
}

- (NSEnumerator *)enumeratorOfHasLocations
{
    return [self.hasLocations objectEnumerator];
}

- (GroceryLocation *)memberOfHasLocations:(GroceryLocation *)anObject
{
    return [self.hasLocations member:anObject];

}

静态itemNameToObject函数如下所示:

+(GroceryItem *)itemNameToObject:(NSString *)itemName
{
    GroceryItem *groceryItem;

    groceryItem = nil;

    if (itemName != nil)
    {
        GroceryManagerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

        NSManagedObjectContext *context = [appDelegate managedObjectContext];

        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        [request setEntity:[NSEntityDescription entityForName:@"GroceryItems" inManagedObjectContext:context]];

        [request setPredicate:[NSPredicate predicateWithFormat:@"name == %@", itemName]];

        NSError *error;
        NSArray *groceryItemObjects = [context executeFetchRequest:request error:&error];

        NSInteger countOfGroceryItems = [groceryItemObjects count];

        if (countOfGroceryItems == 1)
        {
            groceryItem = (GroceryItem *)[groceryItemObjects objectAtIndex:0];
        }
    }

    return groceryItem;
}

1 个答案:

答案 0 :(得分:1)

(来自评论:) 崩溃是由于实体被声明为“GroceryItems”,但“hasLocations”是“GroceryItem”类的属性。获取请求返回一个“GroceryItems”对象数组,这些对象不响应“hasLocations”方法。

通常不需要实现Core Data访问器方法,它们是在运行时动态创建的。