Search code examples
ioscore-dataentity-relationshipnsmanagedobject

Managed Object in Core Data entity causing "is not key value coding-compliant for key" error


I'm pretty new to Core Data, and objective-c. I have been up and down the Core Data documentation, and don't know what I'm doing wrong here.

At runtime, I'm getting the following error when adding the NSManagedObject "ReportItem" to the NSMutableSet "reports" in the NSManagedObject "RoomItem": NSUnknownKeyException', reason: '[<RoomItem 0x747c850> valueForUndefinedKey:]: the entity RoomItem is not key value coding-compliant for the key "reports"

The error is occurring inside of the "RoomList" store class in the "creatReportForRoom" method below, which is called upon viewWillDisapear in the UIViewController where the relevant data is entered:

- (ReportItem *)creatReportForRoom:(RoomItem *)currentRoom Report:(ReportItem *)report
{
    NSDate *dateCreated = [NSDate date];

    ReportItem *detailItem = [NSEntityDescription insertNewObjectForEntityForName:@"ReportItem" inManagedObjectContext:context];

    [detailItem setDateReportCreated:dateCreated];

    NSMutableSet *reports = [currentRoom mutableSetValueForKey:@"reports"];

    [reports addObject:detailItem];  //error is occurring at this line

    [allReports addObject:detailItem];
    return detailItem;
}

The "RoomItem" NSManagedObject files are here:

RoomItem.h

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

@interface RoomItem : NSManagedObject

@property (nonatomic, strong) NSString *building;
@property (nonatomic, strong) NSString *room;
@property (nonatomic, retain) NSString *imageKey;
@property (nonatomic, retain) UIImage *buildingImage;
@property (nonatomic, strong) UIImage *buildingThumbnail;
@property (nonatomic, strong) NSData *buildingThumbnailData;
@property (nonatomic) double objectIndex;
@property (nonatomic, strong) NSDate *dateCreated;

@property (nonatomic, retain) NSMutableSet *reports;

@end

RoomItem.m

#import "RoomItem.h"

@implementation RoomItem

@dynamic building, buildingThumbnail, buildingThumbnailData, objectIndex, room, dateCreated, imageKey, buildingImage, reports;

@end

I've including the "createItem" method were the RoomItem is created and stored, in case I'm doing something wrong there:

- (RoomItem *)createItem
{
    double order;

    //create new roomItem
    //tracks what number item it's creating
    if ([allItems count] == 0) {
        order = 1.0;
    }
    else
    {
        order = [[allItems lastObject] objectIndex] + 1;
    }
    NSLog(@"Adding after %d items, order = %.2f", [allItems count], order);

    RoomItem *detailItem = [NSEntityDescription insertNewObjectForEntityForName:@"RoomItem"
                                                    inManagedObjectContext:context];
    [detailItem setObjectIndex:order];
    [detailItem setDateCreated:[NSDate date]];

    [allItems addObject:detailItem];

    return detailItem;
}

Data Model with relationships: enter image description here

Relationship Diagram: enter image description here

Any advice on fixing this problem would be hugely appreciated. Please let me know if there's anything I failed to include that might help.

Thanks!


Solution

  • There is a discrepancy between the Core Data model shown in your image and your code.

    • In the model image, reports is a relationship from ReportItem to RoomItem.
    • Your code treats it as a relationship from RoomItem to ReportItem.

    If the latter is what you want, then you have to name the relationships in the Core Data model editor correctly: reports as a relationship on RoomItem and roomReportsFor as the inverse relationship on ReportItem.

    I also strongly recommend that you don't write the managed object subclass files yourself, but let it generate by Xcode: Select the entities in the Core Data model editor, and choose "Editor -> Create NSManagedObject Subclass ..." from the menu.

    There is another error in your "RoomItem.h" file: The data type for to-many relationships is NSSet, not NSMutableSet.

    Using the Xcode created managed object subclass files helps to avoid such inconsistencies and errors. You only have to remember to re-created the files after changes in the Core Data model.

    (Just for the sake of completeness: There are also other tools to create the managed object subclasses, such as mogenerator, which some people recommend.)


    This is a simplified version of what I think the relationships should look like:

    enter image description here

    • reports: from RoomItem to ReportItem (to-many relationship),
    • room: from ReportItem to RoomItem (to-one relationship, inverse of reports).