OutlineGroup and hierarchical List with Core Data

Given a NSManagedObject like below:

Code Block
public class Folder: NSManagedObject, Identifiable {
@NSManaged public var name: String
@NSManaged public var position: Int16
@NSManaged public var parentFolder: Folder?
@NSManaged public var folders: Set<Folder>
}

I'd like to use the new OutlineGroup to build an outline view of the folder structure using a FetchRequest.

Code Block
struct FolderView {
@FetchRequest(entity: Folder.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Folder.position, ascending: true)]) var folders: FetchResults<Folder>
var body: some View {
OutlineGroup(folders, children: \.folders) { folder in
Label(folder.name, systemImage: "folder.fill")
}

But this doesn't compile, with the following error:

Key path value type 'Set<Folder>' cannot be converted to contextual type 'FetchedResults<Folder>?'

Any idea?
As a bonus, the children should also be ordered by the position (because it's a Set, it's unordered)…


I converted both the relation and the fetch-results to arrays. Give it a try:

Code Block
extension Folder : Identifiable {
    public var foldersArray: [Folder]? {
        let set = folders as? Set<Folder> ?? []
        return Array(set)
    }
}
struct FolderView {
@FetchRequest(entity: Folder.entity(),sortDescriptors: [NSSortDescriptor(keyPath: \Folder.position, ascending: true)])
var folders: FetchResults<Folder>
    func foldersArray() -> [Folder] {
        return Array(folders)
    }
    var body: some View {
        OutlineGroup(foldersArray(), children:\.foldersArray) { folder in
            Label(folder.name, systemImage: "folder.fill")
        }
    }
}

In addition to my previous, answer you can use List with the children param instead of OutlineGroup to get table row styling.
Did you find a solution yet? I have the same requirement.

The solution to convert to array, by malc, is not feasible as it's not updated when the fetched results change.
I'm in the same boat.

But I have a hierarchical relationship with 3 different entities:

CDCategory ->> CDForm ->> CDSearch ->> CDSearch

A Search can have a list of child Searches and a Search can represent a folder. So basically any number of nested folders/searches.

For example:

Code Block
> Personal (CDCategory)
> My Movie Library (CDForm)
> Searches by Genre (CDSearch with isFolder = true)
Action Movies (CDSearch)
Comedies (CDSearch)


and so on.

I can't seem to get OutlineGroup to handle this. The first issue is the error about NSSet not being the required Set<Form>, etc. To get around that I'm using

Code Block
Array(category.forms as! Set<CDForm>)


I use that with List but I can't seem to use it with OutlineGroup because when I provide the children key path, I get that similar error:

Key path value type 'NSSet?' cannot be converted to contextual type '[CDSearch]?'

I've looked around for examples that use OutlineGroup with Core Data but haven't found anything yet.

Code Block
OutlineGroup(Array(form.searches as! Set<CDSearch>), id: \.uuid, children: \.searches) { (search : CDSearch) in
SearchRow(search: search)
}

I'm afraid i'm in a similar situation. while @malc's response seems aimed at turning the return of the FetchRequest into an array, the problem I'm seeing is that the 'children' parameter is not compatible with the CoreData output of a relationship.

@Cody Brimhall, @Curt Clifton - Is it possible to get some sample code showing how Apple envisions this working? Given what I'm seeing now, it almost looks like I'll need to ignore the OutlineGroup, and build a custom component out of disclosures. I'm wanting to confirm that I've exhausted all possibilities before doing so.
My Solution for this problem is the follow:

Element is a NSManagedObject with property children

Code Block
 @FetchRequest(
    entity: Element.entity(),
    sortDescriptors: []
  ) var endpoints: FetchedResults<Element>
// use auxiliar function for transform fetch to Array
 func data() -> [Endpoint]{
    var data : [Endpoint] = []
    endpoints.forEach { data.append($0) }
    return data
  }
//in body
// List consume data from auxiliar function
 List(data(), id: \.self, children: \.wrapperChildren) {item in
          Text("\(item.name!)")
}
//Finally, Create a extension for you object
extension Element {
   
    var wrapperChildren: [Element]? {
      get {
//this validation is important, for dont show arrow expand in List
        if self.children?.count == 0 {
          return nil
        }
        return self.children?.allObjects.map{$0 as! Endpoint}
      }
    }
}


that code is 100% functionally

The problem that I'm having with this wrappedArray "solution" is that it does not work when adding/removing elements, a List or ForEach needs to be "reload" to be updated (like when you leave a view and enter again).

Core Data must have a proper way to do this, it's the most basic scenario for entities relationships.
OutlineGroup and hierarchical List with Core Data
 
 
Q