0

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!

RoboArch
  • 453
  • 1
  • 6
  • 17

2 Answers2

3

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).
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • I guess I'm a bit confused about whether "reports" is a relationship from ReportItem to RoomItem, or vice versa. The big picture is that there are many rooms, with more being created over time. Associated with each of those rooms would be a series of reports. I've posted a diagram of the relationships in the original post to illustrate my intentions. Given that, how does the relationship need to be set up? – RoboArch Dec 16 '12 at 17:55
  • @RoboArch: But then "reports" should be a relationship from RoomItem to ReportItem. For a `RoomItem *room`, `room.reports` would then be the set of associated reports. – Martin R Dec 16 '12 at 18:00
  • @RoboArch: I have added a description to my answer what I think is the correct model for your situation. – Martin R Dec 16 '12 at 18:10
1

I have experienced this as well when updating the Core Data model. In some cases it seems as the simulator holds on to the old model. This can usually be fixed by deleting the app from the simulator and clean/build.

johan
  • 6,578
  • 6
  • 46
  • 68
  • I've tried that, I still get the same error though. I also restarted my computer, as suggested in other related threads. I must be missing something, like a fetch or something else I don't know about. – RoboArch Dec 16 '12 at 01:12