Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone Core Data relationship fault

I am building a core data iphone app, and having trouble with retrieving one-many relationship data. Please bear with me while I explain.

I have used the data model designer to setup an entity called "Item" that contains many entities called "Comment". I then retrieve multiple entities and display them in a UITableView. I fetch these entities like this (in the viewDidLoad method):

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Items" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(Item_to_Areas.Name LIKE %@)",[areaManagedObject valueForKey:@"Name"]];
[request setPredicate:predicate];
[request setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:@"Item_to_item_comments"]];
NSLog(@"Results: %@", [mutableItemsFetchResults description]);
mutableItemsFetchResults = [[managedObjectContext executeFetchRequest:request error:nil] mutableCopy];
[request release];

When the user taps on a row, I select the particular entiny, pass it to a new table view controller in its init method, and push the new view controller to the stack:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"itemObject: %@", [mutableItemsFetchResults objectAtIndex:indexPath.row]);
InspectionItemCommentsViewController *itemCommentsViewController =     [[InspectionItemCommentsViewController alloc]
                                                                initWithManagedObjectContext:self.managedObjectContext 
                                                                itemObject:[mutableItemsFetchResults objectAtIndex:indexPath.row]];
itemCommentsViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:itemCommentsViewController animated:YES];
[itemCommentsViewController release];
}

In the first block the NSLog output shows that the "Item_to_item_comments" relationship entities were retrieved, but in the second, that it wasn't even though I invoked [request setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:@"Item_to_item_comments"]].

Here is part of the first NSLog output:

Results: (
"<NSManagedObject: 0xb356b70> (entity: Items; id: 0xb34fe60 <x-coredata://E43A90B5-AF0E- 4394-B4A7-5EFE74E181F8/Items/p1> ; data: {\n    Clean = nil;\n    Description = \"\";\n    ItemToInformation = \"<relationship fault: 0x5e1ef00 'ItemToInformation'>\";\n    \"Item_to_Areas\" = \"0xb33fd30 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Areas/p1>\";\n    \"Item_to_item_comments\" = \"<relationship fault: 0x5e1d300 'Item_to_item_comments'>\";\n    Keys = nil;\n    Name = Other;\n    \"Tenant_agrees\" = nil;\n    Undamaged = nil;\n    Working = nil;\n})",
"<NSManagedObject: 0xb35a930> (entity: Items; id: 0xb32acc0 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Items/p2> ; data: {\n    Clean = nil;\n    Description = \"\";\n    ItemToInformation = \"<relationship fault: 0x790de40 'ItemToInformation'>\";\n    \"Item_to_Areas\" = \"0xb33fd30 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Areas/p1>\";\n    \"Item_to_item_comments\" =     (\n        \"0xb35bcb0 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Item_Comments/p13>\",\n        \"0xb35bcd0 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Item_Comments/p37>\",\n        \"0xb35bca0 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Item_Comments/p5>\",\n        \"0xb35bcc0 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Item_Comments/p26>\"\n    );\n    Keys = nil;\n    Name = Lights;\n    \"Tenant_agrees\" = nil;\n    Undamaged = nil;\n    Working = nil;\n})",

You can see that the Items entities are fetched, including Item_to_item_comments. Here's the second NSLog:

itemObject: <NSManagedObject: 0xe20af50> (entity: Items; id: 0xe209fc0 <x- coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Items/p2> ; data: {
    Clean = nil;
    Description = "";
    ItemToInformation = "<relationship fault: 0xe302e40 'ItemToInformation'>";
    "Item_to_Areas" = "0xe500b90 <x-coredata://E43A90B5-AF0E-4394-B4A7-5EFE74E181F8/Areas/p1>";
    "Item_to_item_comments" = "<relationship fault: 0xe302e60 'Item_to_item_comments'>";
    Keys = nil;
    Name = Lights;
    "Tenant_agrees" = nil;
    Undamaged = nil;
    Working = nil;

})

Now, Item_to_item_comments is fault. Similarly, in the pushed view controller, the Items entity is passed, but Item_to_item_comments is not.

I think I am missing something obvious, but after a day spend on this problem, I can't figure it out.

Any help would be appreciated.

Peter

like image 530
futureshocked Avatar asked Jan 22 '23 20:01

futureshocked


1 Answers

A "fault" doesn't mean an error, it just means that the object returned is a "ghost" without its attributes read in. It's normal to get faults for the other side of relationship because you don't what a fetch to set off an uncontrolled cascade of object creation via its relationships.

When you access an attribute of the fault, it will be faulted in as a fully functional object.

Edit:

From comment:

The problem is that I am requesting such relationship through NSLog, but I still can't get the relationship entities.

No you're not. Your just requesting the Items entities themselves and then logging them. They are returning faults for their relationships as expected. Only if you ask each for the actual object on the other side of the relationship are you guaranteed to see an object instead of a fault.

This is what you need to force the faulting-in of the objects in the relationship:

NSLog(@"itemObject.Item_to_item_comments: %@", [mutableItemsFetchResults objectAtIndex:indexPath.row].Item_to_item_comments.someAttribute]);

You're other problem is that you are comparing the results of two seperate fetches. This:

NSLog(@"Results: %@", [mutableItemsFetchResults description]);
mutableItemsFetchResults = [[managedObjectContext executeFetchRequest:request error:nil] mutableCopy];

... logs the mutableItemsFetchResults before the fetch occurs. The next NSLog (presumably) logs the results after the fetch. This means you're looking at possibly two different sets of objects in two different fault states.

You may also have a problem because mutableItemsFetchResults is apparently a property but you're not using the self.mutableItemsFetchResults notation to make sure it is properly retained. Also, I don't think you need themutableCopy.

like image 124
TechZen Avatar answered Jan 31 '23 09:01

TechZen