I keep circling back to this issue, and I hope someone can clarify it for me. I can accomplish this with a combination of List and ForEach, but it seems like a hack and there should be a simple straight forward solution.
The idea is I have an Entity that is elements of both their own children and it's parents. Every element can have more zero or more elements as it's children (nested) and it can also have one other element that is it's parent (except for the root element which has no parent). So, the Entity has a relationship with itself as parent, and an inverse relationship of children.
I am running the latest beta of both XCode and MacOS 11, and the latest SwiftUI. I am building for MacOS, not iOS or iPadOS:
I want to read that entity in HomeView (ContentView):
Then I want to create/display a hierarchtical list - which it would seem should be this simple:
This works if I leave out the children argument, but that only displays the list of top level parents. If I include the children argument, I get an error:
This makes since, because the List is expecting a children argument that is an Array of "elements" (whatever class the first argument is).
I obviously can convert the NSSet returned from the FetchRequest into an array of elements, but the problem with that is that I am then sticking my finger in and stirring the ManagedObject system in Coredata, since any changes that occur to those elements in the array become MY responsibility to track.
It seems like such a basic fundamental pattern for SwiftUI using Coredata, but I can't figure out a "clean" solution.
Any suggestions would be greatly apprecaited. (I expect the solution is going to be to wait until Apple accomodates this - sigh...)
I actually had the same problem with creating a dynamic sidebar for iOS and iPadOS. I got this working but you need to do a whole lot more to get around the problem that children have to be the same type as the parent. I followed Paul's tutorial on this, of course, this tutorial doesn't cover CoreData.
But unfortunatley, it's a whole lot more code than only a single line.
I have consideered going that route, and what I am having troule with is maintaining a single source of truth. I always end up having to keep the view model in sync with the coredata model, and that is not (if I understand it correctly) the "right way" for SwiftUI.
I am trying to come up with an extension to my Elements class (core data model) what Paul calls "wrapped" values. Basically Set/Gets for each attribute. The one that give me indigestion (of course) is the "Element.children" which is a relationship that is one to many and therefore ends up being an NSSet.
I need/want to transparently end up with childrenUnwrapped being an Array that doesn't give the List... indigestion.
I have gotten to this, but it still feels clunky:
This in my Element Extension:
This is the test body:
The result works - the outer list lists all the "top level parents" and the inner list handles each of thier children.
When I say it works, I mean it iterates through the items, but it looses the heirachtical relationship between the top level elements and the children.
SAVE 50% To celebrate WWDC21, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.
You need to create an account or log in to reply.
All interactions here are governed by our code of conduct.
Link copied to your pasteboard.