I have an Order which has a "to-many" relationship with Units. When I try to log the units (NSSet) in Order, I get a fault error:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Order" 
                                          inManagedObjectContext:mainContext];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [mainContext executeFetchRequest:fetchRequest 
                                                     error:nil];
for (Order *order in fetchedObjects) {

    NSLog(@"%@", [order units]);
    break;
}        
[fetchRequest release];

results in:

Relationship 'units' fault on managed object (0x6d9dd00) <Order: 0x6d9dd00> (entity: Order; id: 0x6d88e40 <x-coredata://97A3F3D5-ABA7-499A-A460-5E25CF49C528/Order/p1> ; data: {
    composition = Hemlock;
    condition = "";
    consignee = "";
    consigneeCompanyName = "";
    contactAlternatePhone = "";
    contactEmail = "";
    contactFirstName = "";
    contactLastName = "";
    contactPhone = "";
    customer = "Havard Empire";
    customerCompanyName = "";
    customerNotes = "";
    dateDue = "1/13/2012 12:00:00 AM";
    dateEntered = "1/6/2012 12:00:00 AM";
    dateOrdered = "1/6/2012 12:00:00 AM";
    deliveryAddress1 = "";
    deliveryAddress2 = "";
    deliveryCity = "";
    deliverySpecialInstructions = "";
    deliveryState = "";
    deliveryZip = "";
    depth = 01;
    detail = "";
    freightRate = "";
    grade = Cull;
    instructionsDirectionsNotes = "";
    lastUpdated = "1/6/2012 3:00:43 PM";
    length = 01;
    location = "Lucedale, ms";
    matsPerLoad = "";
    memoLineNotes = "";
    notes = "";
    orderID = 201205134922479;
    orderNumber = 01062012;
    pUP = Cable;
    pricePerItem = "";
    purchaseOrderNumber = "";
    pushToQuickBooks = True;
    quantity = 0;
    quickbooksCompany = 1;
    salesman = "Accounting Adj";
    separateRate = False;
    taxRate = "";
    totalLoads = "";
    type = "2ply Mat";
    units = "<relationship fault: 0x6dacf20 'units'>";
    vendorID = 10;
    width = 01;
})

The units aren't printed. It says "<relationship fault: 0x6dacf20 'units'>";

Also, why is it printing the entire object when I only want units?


Solution 1:

This isn't an error - it is a feature of Core Data called 'faulting'. Here is Apple's description:

Faulting reduces the amount of memory your application consumes. A fault is a placeholder object that represents a managed object that has not yet been fully realized, or a collection object that represents a relationship:

A managed object fault is an instance of the appropriate class, but its persistent variables are not yet initialized. A relationship fault is a subclass of the collection class that represents the relationship. Faulting allows Core Data to put boundaries on the object graph. Because a fault is not realized, a managed object fault consumes less memory, and managed objects related to a fault are not required to be represented in memory at all.

If you want to see each Unit object then you will have to specifically access them. Try the following:

for (Order *order in fetchedObjects) {
    for (Unit *unit in [order units]) {
       NSLog(@"%@", unit);
       //I am not at a computer, so I cannot test, but this should work. You might have to access each property of the unit object to fire the fault, but I don't believe that is necessary.
    }
}     

Solution 2:

In order to see all the objects of a "to-many" relationship, you can call it with the allObjects method of the relationship's NSSet.

In your specific case, the code to print all the Units of the first Order in fetchedObjects would be like this:

for (Order *order in fetchedObjects) {
    NSLog(@"%@", [order.units allObjects]);
    break;
}

Solution 3:

In Swift it would go like so:

for order in fetchedObjects {
    for unit in order.units.allObjects as [Unit] {
        println(unit)
    }
}

Solution 4:

Yep, I had also the same problem. Try just print some field of this table, in example:

    for(Category *category in fetchedObjects) 
    {
        for(Cards *card in category.cards) 
        {
            NSLog(@"Question %@", card.question);
            NSLog(@"Card %@", card);
        }
    }

Solution 5:

This is very counter intuitive. I scratched my head for about a whole day until I realised that I cannot print out the whole NSSet object or each NSManagedObject in the set like so :

for (Order *order in fetchedObjects) {
   for (Unit *unit in [order units]) {
      NSLog(@"%@", unit);
   }
}

This will generate fault in xcode .. But If I print out each attribute in each NSMangedObject, it is fine. I guess Apple has memory concern over Auto-loading to-many objects. In a scenario where there is a chain of to-many relationships, it will consume a lot of memory. So need to lazy-load each attribute.

for (Order *order in fetchedObjects) {
   for (Unit *unit in [order units]) {
      NSLog(@"Unit Name : %@", unit.name);
   }
}

That will print out the unit name..