Question

I have a Department entity which has a one-to-many relationship to an Employee entity. During runtime, for each Department object I want to maintain a sorted array of Employee objects (sorted according to some attribute) which will be used as a model in various view objects.

From what I read there are two ways to represent the sorted array:

Rep1: defining a fetched property in Department (sorting is done by Core Data);

Rep2: maintaining an instance variable sortedEmployees (NSArray of Employee objects) in Department (sorting is done by my code).

Now my real problem is, when the app starts up I have a large number of Departments and Employees to fetch from the persistent store. I want to perform the sorting in the background so as not to block the UI.

I have tried several methods which all ended up in futility:

Method1 (using Rep1): In background threads (using an NSOperationQueue), fetch all Departments, then execute each one's fetched property. Then back in the main thread, find the corresponding Department object in the main thread's managed object context (MOC) (by NSManagedObjectID) and use the fetched property. Problem with Method1: The fetched property in the main thread's Department object isn't populated even after the background Department's fetch is done, which means that it's re-fetched in the main thread Department! This defeats the whole purpose of background fetch. Am I wrong in assuming that a fetched property, once fetched, exists in all MOCs?

Method2 (using Rep2): In background threads (using an NSOperationQueue), fetch all Departments, then compute each one's sortedEmployees array. Then back in the main thread, find the corresponding Department object in the main thread's MOC (by NSManagedObjectID) and set the aforementioned array to this object. Problem with Method2: The objects in the sortedEmployees array are Employee objects belonging to the background thread's MOC. When the main thread attempts to access them later, crash would occur with something like "NSManagedObject with ID ... has been invalidated." This is because each thread must have its own MOC (and its associated managed objects).

So how does one sort managed objects in the background at all, if the managed objects cannot exist across thread boundaries? Am I missing something?

Was it helpful?

Solution

Pius,

You aren't missing anything. You just need to convert your sorted array to the new MOC. Here's a fragment:

NSMutableArray *ma = [NSMutableArray arrayWithCapacity: array.count];

for (mo in array) {

    [ma addObject: [moc objectWithID: mo.objectID]];
}
return ma;

That will migrate your array. As I understand it, this is an efficient process. Furthermore, you can depend upon the row cache for high performance access to properties.

Andrew

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top