4
votes

I've got a sample project at

https://github.com/ericgorr/LazyFetching

The setup is pretty straightforward. In my CoreData model, I have two entities:

  1. Shelf which has a name property and a to-many relationship (items) to the Item entity
  2. Item which has a name property has a relationship to the Shelf entity (it's "parent")

I then have two NSArrayControllers:

Shelf Array Controller with the Mode 'Entity Name', the Entity Name of 'Shelf'. It Prepares Content and using Lazy Fetching.

Item Array Controller with the Mode 'Entity Name', the Entity Name of 'Item'. It does not prepare content and does not use lazy fetching. It's Content Set is bound to the Shelf Array Controller's selection and 'items' property.

On the Window, I've got two NSTableViews and two + buttons, each ties to one of the array controllers.

What I did was to:

  1. Press the top + button and named the new Shelf entry 'a'
  2. Press the top + button again and named the Shelf entry 'b'
  3. Pressed the top column header to sort the Shelf entries in ascending order.
  4. Make sure the 'b' entry is selected
  5. Pressed the bottom + button and renamed the Item entry to anything

What I see happen then is the rows in the upper (Shelf) table change order so that the 'b' entry is listed first.

If I press the Info button, what it will do is:

  1. NSLog the sort descriptors for the Shelf Array Controller
  2. Print the names of the entries in the arrangedObjects array of the Shelf Array Controller
  3. Call rearrangeObjects on Shelf Array Controller
  4. Print out the names of the entries in the arrangedObjects array of the Shelf Array Controller

After all of this, I see, as expected, a single sort descriptor on the Shelf Array Controller: name, ascending, compare:

And the following output for arrangedObjects:

2013-05-19 16:08:56.023 LazyFetching[11791:303] b

2013-05-19 16:08:56.024 LazyFetching[11791:303] a

and

2013-05-19 16:08:56.024 LazyFetching[11791:303] b

2013-05-19 16:08:56.024 LazyFetching[11791:303] a

For some reason, it is no longer sorting the items in the Shelf Array Controller.

If I turn off Lazy Fetching for the Shelf Array Controller, everything seems to work correctly.

So, what I don't understand is why I am seeing this behavior with Lazy Fetching enabled. It seems possible that it is a bug. If so, I can certainly file what is likely to be a duplicate report. But, I am guessing, there is some good explanation and a standard way of dealing with it so items remain sorted by the sort descriptors in the arrangedObjects array of the array controller.

1

1 Answers

0
votes

I found the only way I could force sorting after turning on lazy fetching for an NSArrayController (in IB) was to send a performSelector:withObject:afterDelay: in awakeFromNib with the delay set to 0:

  • (void)awakeFromNib { [self performSelector:@selector(sort) withObject:self afterDelay:0.0]; }

  • (void)sort {

    NSSortDescriptor* sorting = [NSSortDescriptor sortDescriptorWithKey:@"" ascending:YES];

    [self.AC_Controller setSortDescriptors:[NSArray arrayWithObject:sorting]]; }

These methods were included in my main window controller where the NSArrayController resides in the associated nib file.

  • it seems that upon loading the nib containing the NSArrayController, the nib loading machinery invokes lazy fetching as per the IB setting but this overrides any sorting you may be trying to set programmatically or via IB in the NSTableView - by waiting for the next run loop the sorting will then "take" OK.

This code assumes you have an IBOutlet connected to the NSArrayController of course.