Your getting the normal return for a fetched relationship. What you have is a fault i.e. the ghost of an object. The actual managed objects are not loaded in until you try to access one their attributes directly.
Core Data uses faults in relationships to prevent having to load a vast number of objects into memory just to find one small piece of data. Suppose you have a relationship with a 1,000 managed objects on the other side and you need one integer value from one of those managed objects. Without faulting, Core Data would have to load 1,000 objects into memory just to find and retrieve 32-bits of data. With faulting, Core Data knows where the integer value is and can go get that one object with its one value.
You can treat a fetched property just like an array. Take the case of this simple managed object subclass in which theFetchedProperty
is a fetched property with a predicate of "TestEntity.order>5"
@interface TestEntityMO : NSManagedObject
{}
@property (nonatomic, retain) NSNumber * order;
@property(nonatomic, retain) NSArray *theFetchedProperty;
Set up like this:
TestEntityMO *testMO;
for (int i=0; i<10; i++) {
testMO=[NSEntityDescription insertNewObjectForEntityForName:@"TestEntity" inManagedObjectContext:self.managedObjectContext];
testMO.order=[NSNumber numberWithInt:i];
}
Then log the the last TestEntityMO object created. The first time you log the property, it returns a fault:
NSLog(@"testMO.theFetchedProperty.theFetchedProperty == %@",testMO.theFetchedProperty);
outputs
testMO.theFetchedProperty.theFetchedProperty == Relationship fault for (<NSFetchedPropertyDescription: 0x3d19210>), //... rest removed for brevity
... but you can log the count of the fetched property just like an array:
NSLog(@"[testMO.theFetchedProperty count] == %d",[testMO.theFetchedProperty count] );
... outputs:
[testMO.theFetchedProperty count] == 4
You can get the object at an index just like an array:
NSLog(@"[testMO.theFetchedProperty objectAtIndex:0] == %@",[testMO.theFetchedProperty objectAtIndex:0]);
... outputs the description of a TestEntityMO object (which may or may not be fault. In this case not):
[testMO.theFetchedProperty objectAtIndex:0] == <TestEntityMO: 0x3d20a70> (entity: TestEntity; id: 0x3d20ab0 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A11> ; data: {
order = 9;
theFetchedProperty = (
0x3d20ab0 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A11>,
0x3d20a00 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A10>,
0x3d20880 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A8>,
0x3d20970 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A9>
);
})
Logging the value of an attribute of a random object:
NSLog(@"[[testMO.theFetchedProperty objectAtIndex:0] order] == %@",[[testMO.theFetchedProperty objectAtIndex:1] order]);
... outputs:
[[testMO.theFetchedProperty objectAtIndex:1] order] == 8
However, if you log the fetched property a second time after you trigger the fetch by the code above you get a actual objects:
NSLog(@"testMO.theFetchedProperty == %@",testMO.theFetchedProperty);
... outputs:
testMO.theFetchedProperty == Relationship objects for (
<TestEntityMO: 0x3d20a70> ... ;
data: {
order = 9;
theFetchedProperty = (
0x3d20ab0 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A11>,
0x3d20a00 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A10>,
0x3d20880 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A8>,
0x3d20970 <x-coredata:///TestEntity/t3A79EE49-39F4-4FCA-8E25-0C28B8E0E01A9>
);
}),...
In summation you can:
- Treat fetched relationships just like NSArrays in code.
- As with all managed objects, you will often see a fault if you log the object directly.