1

I'm using an NSTreeController set in entity mode, to manage a hierarchy of folders (a core data entity I call Folder). The "Children" key path is set to an NSArray readwrite property of Folder, which I call subfoldersArray. (I use NSArray because NSOrderedSet doesn't work with a tree controller).

When the user moves a folder to another folder (via an NSOutlineView) or at a different position of the same parent folder, the app calls moveNode:toIndexPath: on the tree controller. I use this method as it preserves the selection (while changing the underlying model tends to deselect the selected folder, even though the controller has preserveSelection set to YES.

Problem: every Folder instance that is moved by moveNode:toIndexPath: is placed at the end of the subfoldersArray, regardless of the index path specified. This happens only when the NSTreeController controls an NSManagedObject subclass (in either class or entity mode).

The exact same moveNode:toIndexPath: instruction on the same NSTreeController controlling an equivalent NSObject subclass (with an identical subfoldersArray property) works as expected.

I'd like a solution that doesn't involve setting the underlying model myself, as this tends to deselect the selected folder (which may not be the one that is moved).

jeanlain
  • 382
  • 1
  • 3
  • 13
  • Is the issue reproducable in a small test project without Core Data? – Willeke Dec 10 '22 at 13:12
  • See my edits. I found that the issue only happens if the tree controller controls an `NSManagedObject` subclass. Very weird. I can provide a link to a small project if you want to test. – jeanlain Dec 10 '22 at 19:13
  • NSManagedObject is an interface to Core Data, yes? Well, Core Data thinks entirely in sets; there is no such thing as an array as far as Core Data is concerned. So I would not expect an inserted object to be at _any_ particular position in an array that is being read into Core Data and back; the array-ness (i.e. the order) would be destroyed by such an operation. The usual thing (see e.g. https://stackoverflow.com/questions/21123519/does-core-data-persist-the-order-of-objects-in-nsmutablearray) is to give your entities a property _you_ can sort on as you retrieve the set. – matt Dec 11 '22 at 01:09
  • ^ This is what I'm doing by using an `NSArray` property rather than a set (`NSTreeController` doesn't work with ordered sets). But why would `NSTreeController` set the array property differently depending on the class of the object it manages? – jeanlain Dec 11 '22 at 08:34
  • Experiment: implement `addSubfoldersArrayObject:`, `removeSubfoldersArrayObject:` and the other Core Data relationship methods on `Folder`. – Willeke Dec 11 '22 at 11:23
  • `subfoldersArray` is not a core data relationship since it is an NSArray. Anyway, I can modify the underlying model just fine, no problem. But when I do, the selected folder in the outline view gets deselected (even though the tree controller is set to maintain the selection.) I can re-select the folder in code just after the change, but its content (which can be other entities) still get deselected. This doesn't happen if I use `moveNode:toIndexPath:`, but then the underlying model is not in sync. I ended up calling `moveNode:toIndexPath`: and changing the underlying model as well. – jeanlain Dec 11 '22 at 11:59
  • If the problem is solved, give the solution in the Answer field, or delete the question. Thanks. – matt Dec 11 '22 at 16:02
  • I clarified the solution I'm looking for. It's still not found. And I'm not sure why the issue was downvoted. Do Apple state that `moveNode:toIndexPath:` would always place the moved item at the end of the destination array if this array just happens to be a property of some `NSManagedObject` subclass? I don't think so. – jeanlain Dec 11 '22 at 17:39
  • If I let Xcode generate a NSManagedObject subclass the I get a category `CoreDataGeneratedAccessors` with `insertObject:inSubfoldersAtIndex:`, `removeObjectFromSubfoldersAtIndex:` etc. Implement these methods for `subfoldersArray` and modify `folders`. (It's a hack) – Willeke Dec 12 '22 at 12:46
  • I tried modifying the underlying model myself (not easy). The selection is preserved except when it's the dragged item(s). – Willeke Dec 12 '22 at 14:08
  • Thanks for testing. I use the methods you mention to modify the underlying model. The problem is that doing so does not preserve the selection in all situations. – jeanlain Dec 12 '22 at 18:39

0 Answers0